From edcb51e041d612e3fb8a0c0a9135d989c881ccc9 Mon Sep 17 00:00:00 2001 From: Peihsun Yeh Date: Wed, 1 Aug 2018 16:58:31 -0700 Subject: Creating custom media source solution and project (still needs driver) --- .../MediaSource/MediaSource.vcxproj | 141 ++++++ .../MediaSource/MediaSource.vcxproj.filters | 44 ++ .../MediaSource/SimpleMediaSource.cpp | 506 +++++++++++++++++++++ .../MediaSource/SimpleMediaSource.h | 128 ++++++ .../MediaSource/SimpleMediaStream.cpp | 407 +++++++++++++++++ .../MediaSource/SimpleMediaStream.h | 54 +++ general/SimpleMediaSource/MediaSource/dllMain.cpp | 35 ++ general/SimpleMediaSource/MediaSource/module.def | 6 + general/SimpleMediaSource/MediaSource/stdafx.cpp | 11 + general/SimpleMediaSource/MediaSource/stdafx.h | 27 ++ general/SimpleMediaSource/SimpleMediaSource.sln | 31 ++ 11 files changed, 1390 insertions(+) create mode 100644 general/SimpleMediaSource/MediaSource/MediaSource.vcxproj create mode 100644 general/SimpleMediaSource/MediaSource/MediaSource.vcxproj.filters create mode 100644 general/SimpleMediaSource/MediaSource/SimpleMediaSource.cpp create mode 100644 general/SimpleMediaSource/MediaSource/SimpleMediaSource.h create mode 100644 general/SimpleMediaSource/MediaSource/SimpleMediaStream.cpp create mode 100644 general/SimpleMediaSource/MediaSource/SimpleMediaStream.h create mode 100644 general/SimpleMediaSource/MediaSource/dllMain.cpp create mode 100644 general/SimpleMediaSource/MediaSource/module.def create mode 100644 general/SimpleMediaSource/MediaSource/stdafx.cpp create mode 100644 general/SimpleMediaSource/MediaSource/stdafx.h create mode 100644 general/SimpleMediaSource/SimpleMediaSource.sln (limited to 'general/SimpleMediaSource') diff --git a/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj b/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj new file mode 100644 index 00000000..b1f8a7f4 --- /dev/null +++ b/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj @@ -0,0 +1,141 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {43AD9BF7-E765-48FE-9826-71A8F2CB12DD} + MediaSource + 10.0.17134.0 + + + + DynamicLibrary + true + v141 + MultiByte + + + DynamicLibrary + false + v141 + true + MultiByte + + + DynamicLibrary + true + v141 + MultiByte + + + DynamicLibrary + false + v141 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + true + + + mfplat.lib;RuntimeObject.lib;%(AdditionalDependencies) + + + + + Level3 + Disabled + true + true + + + mfplat.lib;RuntimeObject.lib;%(AdditionalDependencies) + + + + + Level3 + MaxSpeed + true + true + true + true + + + true + true + mfplat.lib;RuntimeObject.lib;%(AdditionalDependencies) + + + + + Level3 + MaxSpeed + true + true + true + true + + + true + true + mfplat.lib;RuntimeObject.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj.filters b/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj.filters new file mode 100644 index 00000000..ce4a1433 --- /dev/null +++ b/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj.filters @@ -0,0 +1,44 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Source Files + + + Source Files + + + Source Files + + + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/general/SimpleMediaSource/MediaSource/SimpleMediaSource.cpp b/general/SimpleMediaSource/MediaSource/SimpleMediaSource.cpp new file mode 100644 index 00000000..34b6f2e2 --- /dev/null +++ b/general/SimpleMediaSource/MediaSource/SimpleMediaSource.cpp @@ -0,0 +1,506 @@ +#include "SimpleMediaSource.h" +#include "SimpleMediaStream.h" + +/////////////////////////////////////////////////////////////////////////////// +HRESULT SimpleMediaSource::RuntimeClassInitialize() +{ + HRESULT hr = S_OK; + + if (SUCCEEDED(hr)) + { + hr = MFCreateAttributes(&_spAttributes, 10); + } + + if (SUCCEEDED(hr)) + { + hr = MFCreateEventQueue(&_spEventQueue); + } + + if (SUCCEEDED(hr)) + { + hr = MakeAndInitialize(&_stream, this); + } + + if (SUCCEEDED(hr)) + { + ComPtr streamDescriptor(_stream.Get()->_spStreamDesc.Get()); + hr = MFCreatePresentationDescriptor(NUM_STREAMS, streamDescriptor.GetAddressOf(), &_spPresentationDescriptor); + } + + if (SUCCEEDED(hr)) + { + _wasStreamPreviouslySelected = false; + _sourceState = SourceState::Stopped; + } + + return hr; +} + +// IMFMediaEventGenerator methods. +/////////////////////////////////////////////////////////////////////////////// +IFACEMETHODIMP SimpleMediaSource::BeginGetEvent(IMFAsyncCallback *pCallback, IUnknown *punkState) +{ + auto lock = _critSec.Lock(); + + HRESULT hr = _CheckShutdownRequiresLock(); + if (SUCCEEDED(hr)) + { + hr = _spEventQueue->BeginGetEvent(pCallback, punkState); + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////// +IFACEMETHODIMP SimpleMediaSource::EndGetEvent(IMFAsyncResult *pResult, IMFMediaEvent **ppEvent) +{ + auto lock = _critSec.Lock(); + + HRESULT hr = _CheckShutdownRequiresLock(); + if (SUCCEEDED(hr)) + { + hr = _spEventQueue->EndGetEvent(pResult, ppEvent); + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////// +IFACEMETHODIMP SimpleMediaSource::GetEvent(DWORD dwFlags, IMFMediaEvent **ppEvent) +{ + // NOTE: + // GetEvent can block indefinitely, so we don't hold the lock. + // This requires some juggling with the event queue pointer. + + HRESULT hr = S_OK; + + ComPtr spQueue; + + { + auto lock = _critSec.Lock(); + + hr = _CheckShutdownRequiresLock(); + if (SUCCEEDED(hr)) + { + spQueue = _spEventQueue; + } + } + + // Now get the event. + if (SUCCEEDED(hr)) + { + hr = spQueue->GetEvent(dwFlags, ppEvent); + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////// +IFACEMETHODIMP SimpleMediaSource::QueueEvent( + MediaEventType eventType, + REFGUID guidExtendedType, + HRESULT hrStatus, + _In_opt_ PROPVARIANT const *pvValue) +{ + auto lock = _critSec.Lock(); + + HRESULT hr = _CheckShutdownRequiresLock(); + if (SUCCEEDED(hr)) + { + hr = _spEventQueue->QueueEventParamVar(eventType, guidExtendedType, hrStatus, pvValue); + } + + return hr; +} + +// IMFMediaSource methods +/////////////////////////////////////////////////////////////////////////////// +IFACEMETHODIMP SimpleMediaSource::CreatePresentationDescriptor( + IMFPresentationDescriptor **ppPresentationDescriptor) +{ + if (ppPresentationDescriptor == nullptr) + { + return E_POINTER; + } + + *ppPresentationDescriptor = nullptr; + + auto lock = _critSec.Lock(); + + HRESULT hr = _CheckShutdownRequiresLock(); + if (SUCCEEDED(hr)) + { + hr = _spPresentationDescriptor->Clone(ppPresentationDescriptor); + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////// +IFACEMETHODIMP SimpleMediaSource::GetCharacteristics(DWORD *pdwCharacteristics) +{ + *pdwCharacteristics = 0; + + auto lock = _critSec.Lock(); + + HRESULT hr = _CheckShutdownRequiresLock(); + if (SUCCEEDED(hr)) + { + *pdwCharacteristics = MFMEDIASOURCE_IS_LIVE; + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////// +IFACEMETHODIMP SimpleMediaSource::Pause() +{ + // Pause() not required/needed for live sources + HRESULT hr = MF_E_INVALID_STATE_TRANSITION; + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////// +IFACEMETHODIMP SimpleMediaSource::Shutdown() +{ + HRESULT hr = S_OK; + { + auto lock = _critSec.Lock(); + + _sourceState = SourceState::Shutdown; + + _spAttributes.Reset(); + _spPresentationDescriptor.Reset(); + + if (_spEventQueue != nullptr) + { + _spEventQueue->Shutdown(); + _spEventQueue.Reset(); + } + + if (_stream != nullptr) + { + _stream.Get()->Shutdown(); + _stream.Reset(); + } + } + return hr; +} + +/////////////////////////////////////////////////////////////////////////////// +IFACEMETHODIMP SimpleMediaSource::Start( + _In_ IMFPresentationDescriptor *pPresentationDescriptor, + _In_opt_ const GUID *pguidTimeFormat, + _In_ const PROPVARIANT *pvarStartPos) +{ + HRESULT hr = S_OK; + + if (pPresentationDescriptor == nullptr || pvarStartPos == nullptr) + { + hr = E_INVALIDARG; + } + else if (pguidTimeFormat != nullptr && *pguidTimeFormat != GUID_NULL) + { + hr = MF_E_UNSUPPORTED_TIME_FORMAT; + } + + do + { + BREAK_ON_FAIL(hr); + + auto lock = _critSec.Lock(); + BREAK_ON_FAIL(hr = _CheckShutdownRequiresLock()); + + if (_sourceState != SourceState::Stopped) + { + hr = MF_E_INVALID_STATE_TRANSITION; + break; + } + + _sourceState = SourceState::Started; + + // This checks the passed in PresentationDescriptor matches the member of streams we + // have defined internally and that at least one stream is selected + BREAK_ON_FAIL(hr = _ValidatePresentationDescriptor(pPresentationDescriptor)); + + DWORD count = 0; + BREAK_ON_FAIL(hr = pPresentationDescriptor->GetStreamDescriptorCount(&count)); + + PROPVARIANT startTime; + BREAK_ON_FAIL(hr = InitPropVariantFromInt64(MFGetSystemTime(), &startTime)); + + // Send event that the source started. Include error code in case it failed. + BREAK_ON_FAIL(hr = _spEventQueue->QueueEventParamVar(MESourceStarted, GUID_NULL, hr, &startTime)); + + // Open and un-pause the selected stream(s) + BOOL selected = false; + ComPtr spStreamDescriptor; + BREAK_ON_FAIL(hr = pPresentationDescriptor->GetStreamDescriptorByIndex(0, &selected, &spStreamDescriptor)); + + DWORD streamIndex = 0; + BREAK_ON_FAIL(hr = spStreamDescriptor->GetStreamIdentifier(&streamIndex)); + + if (streamIndex >= NUM_STREAMS) + { + hr = MF_E_INVALIDSTREAMNUMBER; + break; + } + + if (selected) + { + // Update our internal PresentationDescriptor + BREAK_ON_FAIL(hr = _spPresentationDescriptor->SelectStream(streamIndex)); + BREAK_ON_FAIL(hr = _stream.Get()->SetStreamState(MF_STREAM_STATE_RUNNING)); + + ComPtr spunkStream; + BREAK_ON_FAIL(hr = _stream.As(&spunkStream)); + + BREAK_ON_FAIL(hr = _spEventQueue->QueueEventParamUnk(_wasStreamPreviouslySelected ? MEUpdatedStream : MENewStream, + GUID_NULL, S_OK, spunkStream.Get())); + BREAK_ON_FAIL(hr = _stream.Get()->QueueEvent(MEStreamStarted, GUID_NULL, S_OK, &startTime)); + } + _wasStreamPreviouslySelected = selected; + + } while (false); + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////// +IFACEMETHODIMP SimpleMediaSource::Stop() +{ + HRESULT hr = S_OK; + + do + { + auto lock = _critSec.Lock(); + + if (_sourceState != SourceState::Started) + { + BREAK_ON_FAIL(hr = MF_E_INVALID_STATE_TRANSITION); + } + + BREAK_ON_FAIL(hr = _CheckShutdownRequiresLock()); + + PROPVARIANT stopTime; + BREAK_ON_FAIL(hr = InitPropVariantFromInt64(MFGetSystemTime(), &stopTime)); + + DWORD count = 0; + BREAK_ON_FAIL(hr = _spPresentationDescriptor->GetStreamDescriptorCount(&count)); + // Deselect the streams and send the stream stopped events. + MF_STREAM_STATE state; + hr = _stream.Get()->GetStreamState(&state); + if (FAILED(hr)) + { + continue; + } + _wasStreamPreviouslySelected = (state == MF_STREAM_STATE_RUNNING); + hr = _stream.Get()->SetStreamState(MF_STREAM_STATE_STOPPED); + if (FAILED(hr)) + { + continue; + } + _spPresentationDescriptor->DeselectStream(0); + hr = _stream.Get()->QueueEvent(MEStreamStopped, GUID_NULL, hr, &stopTime); + if (FAILED(hr)) + { + continue; + } + + BREAK_ON_FAIL(hr = _spEventQueue->QueueEventParamVar(MESourceStopped, GUID_NULL, hr, &stopTime)); + + } while (false); + + return hr; +} + +// IMFMediaSourceEx +/////////////////////////////////////////////////////////////////////////////// +IFACEMETHODIMP SimpleMediaSource::GetSourceAttributes(_Outptr_ IMFAttributes **ppAttributes) +{ + if (ppAttributes == nullptr) + { + return E_POINTER; + } + + auto lock = _critSec.Lock(); + + HRESULT hr = _CheckShutdownRequiresLock(); + if (SUCCEEDED(hr)) + { + *ppAttributes = _spAttributes.Get(); + (*ppAttributes)->AddRef(); + } + else + { + hr = E_UNEXPECTED; + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////// +IFACEMETHODIMP SimpleMediaSource::GetStreamAttributes(DWORD dwStreamIdentifier, _Outptr_ IMFAttributes **ppAttributes) +{ + if (ppAttributes == nullptr) + { + return E_POINTER; + } + + auto lock = _critSec.Lock(); + + *ppAttributes = nullptr; + + HRESULT hr = _CheckShutdownRequiresLock(); + if (SUCCEEDED(hr)) + { + if (dwStreamIdentifier >= NUM_STREAMS) + { + hr = MF_E_INVALIDSTREAMNUMBER; + } + else + { + *ppAttributes = _stream.Get()->_spAttributes.Get(); + (*ppAttributes)->AddRef(); + } + } + else + { + hr = E_UNEXPECTED; + } + + return hr; +} + +/////////////////////////////////////////////////////////////////////////////// +IFACEMETHODIMP SimpleMediaSource::SetD3DManager(_In_opt_ IUnknown* /*pManager*/) +{ + // No need to implement this method in our case. + HRESULT hr = E_NOTIMPL; + return hr; +} + +// IMFGetService methods +/////////////////////////////////////////////////////////////////////////////// +_Use_decl_annotations_ +IFACEMETHODIMP SimpleMediaSource::GetService(REFGUID guidService, REFIID riid, LPVOID * ppvObject) +{ + HRESULT hr = _CheckShutdownRequiresLock(); + if (SUCCEEDED(hr)) + { + if (!ppvObject) + { + hr = E_INVALIDARG; + } + else + { + *ppvObject = NULL; + } + + hr = MF_E_UNSUPPORTED_SERVICE; + } + + return hr; +} + +// IKsControl methods +_Use_decl_annotations_ +IFACEMETHODIMP SimpleMediaSource::KsProperty( + PKSPROPERTY pProperty, + ULONG ulPropertyLength, + LPVOID pPropertyData, + ULONG ulDataLength, + ULONG* pBytesReturned) +{ + return E_NOTIMPL; +} + +/////////////////////////////////////////////////////////////////////////////// +_Use_decl_annotations_ +IFACEMETHODIMP SimpleMediaSource::KsMethod( + PKSMETHOD pMethod, + ULONG ulMethodLength, + LPVOID pMethodData, + ULONG ulDataLength, + ULONG* pBytesReturned) +{ + return E_NOTIMPL; +} + +/////////////////////////////////////////////////////////////////////////////// +_Use_decl_annotations_ +IFACEMETHODIMP SimpleMediaSource::KsEvent( + _In_opt_ PKSEVENT pEvent, + _In_ ULONG ulEventLength, + _Inout_opt_ LPVOID pEventData, + _In_ ULONG ulDataLength, + _Out_opt_ ULONG* pBytesReturned) +{ + return E_NOTIMPL; +} + +/////////////////////////////////////////////////////////////////////////////// +HRESULT SimpleMediaSource::_CheckShutdownRequiresLock() +{ + if (_sourceState == SourceState::Shutdown) + { + return MF_E_SHUTDOWN; + } + + if (_spEventQueue == nullptr || _stream == nullptr) + { + return E_UNEXPECTED; + } + + return S_OK; +} + +/////////////////////////////////////////////////////////////////////////////// +HRESULT SimpleMediaSource::_ValidatePresentationDescriptor(IMFPresentationDescriptor *pPD) +{ + if (pPD == nullptr) + { + return E_INVALIDARG; + } + + HRESULT hr = S_OK; + DWORD cStreams = 0; + bool anySelected = false; + + // The caller's PD must have the same number of streams as ours. + hr = pPD->GetStreamDescriptorCount(&cStreams); + + if (SUCCEEDED(hr) && (cStreams != NUM_STREAMS)) + { + hr = E_INVALIDARG; + } + + // The caller must select at least one stream. + for (UINT32 i = 0; SUCCEEDED(hr) && i < cStreams; ++i) + { + ComPtr spSD; + BOOL fSelected = FALSE; + hr = pPD->GetStreamDescriptorByIndex(i, &fSelected, &spSD); + + if (SUCCEEDED(hr)) + { + anySelected |= !!fSelected; + + DWORD dwId = 0; + hr = spSD->GetStreamIdentifier(&dwId); + + if (SUCCEEDED(hr) && dwId >= NUM_STREAMS) + { + hr = E_INVALIDARG; + } + } + } + + if (!anySelected) + { + hr = E_INVALIDARG; + } + + return hr; +} \ No newline at end of file diff --git a/general/SimpleMediaSource/MediaSource/SimpleMediaSource.h b/general/SimpleMediaSource/MediaSource/SimpleMediaSource.h new file mode 100644 index 00000000..85b9227f --- /dev/null +++ b/general/SimpleMediaSource/MediaSource/SimpleMediaSource.h @@ -0,0 +1,128 @@ +#pragma once + +// Represents a simple media source that only has one stream and outputs a static image + +#include "stdafx.h" +#include "SimpleMediaStream.h" + +#define BREAK_ON_FAIL(value) if FAILED(value) break; + +#if !defined(_IKsControl_) +#define _IKsControl_ +interface DECLSPEC_UUID("28F54685-06FD-11D2-B27A-00A0C9223196") IKsControl; +#undef INTERFACE +#define INTERFACE IKsControl +DECLARE_INTERFACE_(IKsControl, IUnknown) +{ + STDMETHOD(KsProperty)( + THIS_ + IN PKSPROPERTY Property, + IN ULONG PropertyLength, + IN OUT LPVOID PropertyData, + IN ULONG DataLength, + OUT ULONG* BytesReturned + ) PURE; + STDMETHOD(KsMethod)( + THIS_ + IN PKSMETHOD Method, + IN ULONG MethodLength, + IN OUT LPVOID MethodData, + IN ULONG DataLength, + OUT ULONG* BytesReturned + ) PURE; + STDMETHOD(KsEvent)( + THIS_ + IN PKSEVENT Event OPTIONAL, + IN ULONG EventLength, + IN OUT LPVOID EventData, + IN ULONG DataLength, + OUT ULONG* BytesReturned + ) PURE; +}; +#endif //!defined(_IKsControl_) + +class SimpleMediaStream; + +class __declspec(uuid("{9812588D-5CE9-4E4C-ABC1-049138D10DCE}")) +SimpleMediaSource : public RuntimeClass< + RuntimeClassFlags, + IMFMediaEventGenerator, + IMFMediaSource, + IMFMediaSourceEx, + IMFGetService, + IKsControl> +{ + + enum class SourceState + { + Invalid, Stopped, Started, Shutdown + }; + +public: + // IMFMediaEventGenerator + IFACEMETHOD(BeginGetEvent)(_In_ IMFAsyncCallback *pCallback, _In_ IUnknown *punkState); + IFACEMETHOD(EndGetEvent)(_In_ IMFAsyncResult *pResult, _Out_ IMFMediaEvent **ppEvent); + IFACEMETHOD(GetEvent)(DWORD dwFlags, _Out_ IMFMediaEvent **ppEvent); + IFACEMETHOD(QueueEvent)(MediaEventType met, REFGUID guidExtendedType, HRESULT hrStatus, _In_ const PROPVARIANT *pvValue); + + // IMFMediaSource + IFACEMETHOD(CreatePresentationDescriptor)(_Out_ IMFPresentationDescriptor **ppPresentationDescriptor); + IFACEMETHOD(GetCharacteristics)(_Out_ DWORD *pdwCharacteristics); + IFACEMETHOD(Pause)(); + IFACEMETHOD(Shutdown)(); + IFACEMETHOD(Start)( + _In_ IMFPresentationDescriptor *pPresentationDescriptor, + _In_ const GUID *pguidTimeFormat, + _In_ const PROPVARIANT *pvarStartPosition); + IFACEMETHOD(Stop)(); + + // IMFMediaSourceEx + IFACEMETHOD(GetSourceAttributes)(_Outptr_ IMFAttributes **ppAttributes); + IFACEMETHOD(GetStreamAttributes)(DWORD dwStreamIdentifier, _Outptr_ IMFAttributes **ppAttributes); + IFACEMETHOD(SetD3DManager)(_In_opt_ IUnknown *pManager); + + // IMFGetService + IFACEMETHOD(GetService)(REFGUID guidService, REFIID riid, _Out_opt_ LPVOID *ppvObject); + + // IKsControl + IFACEMETHOD(KsProperty)( + _In_ PKSPROPERTY pProperty, + ULONG ulPropertyLength, + _Inout_ LPVOID pPropertyData, + ULONG ulDataLength, + _Out_ ULONG* pBytesReturned); + + IFACEMETHOD(KsMethod)( + _In_ PKSMETHOD pMethod, + ULONG ulMethodLength, + _Inout_ LPVOID pMethodData, + ULONG ulDataLength, + _Out_ ULONG* pBytesReturned + ); + + IFACEMETHOD(KsEvent)( + _In_opt_ PKSEVENT pEvent, + ULONG ulEventLength, + _Inout_opt_ LPVOID pEventData, + ULONG ulDataLength, + _Out_opt_ ULONG* pBytesReturned + ); +public: + HRESULT RuntimeClassInitialize(); + +private: + HRESULT _CheckShutdownRequiresLock(); + HRESULT _ValidatePresentationDescriptor(IMFPresentationDescriptor *pPresentationDescriptor); + + CriticalSection _critSec; + SourceState _sourceState{ SourceState::Invalid }; + ComPtr _spEventQueue; + ComPtr _spPresentationDescriptor; + ComPtr _spAttributes; + + bool _wasStreamPreviouslySelected; // maybe makes more sense as a property of the stream + const DWORD NUM_STREAMS = 1; + ComPtr _stream; +}; + +CoCreatableClass(SimpleMediaSource); diff --git a/general/SimpleMediaSource/MediaSource/SimpleMediaStream.cpp b/general/SimpleMediaSource/MediaSource/SimpleMediaStream.cpp new file mode 100644 index 00000000..2f8b603b --- /dev/null +++ b/general/SimpleMediaSource/MediaSource/SimpleMediaStream.cpp @@ -0,0 +1,407 @@ +#include "SimpleMediaStream.h" + +#define NUM_IMAGE_ROWS 240 +#define NUM_IMAGE_COLS 320 +#define BYTES_PER_PIXEL 4 +#define IMAGE_BUFFER_SIZE_BYTES (NUM_IMAGE_ROWS * NUM_IMAGE_COLS * BYTES_PER_PIXEL) +#define IMAGE_ROW_SIZE_BYTES (NUM_IMAGE_COLS * BYTES_PER_PIXEL) + +#define CHECKHR_GOTO( val, label ) \ +hr = (val); \ +if( FAILED( hr ) ) { \ + goto label; \ +} + +HRESULT SimpleMediaStream::RuntimeClassInitialize(_In_ SimpleMediaSource *pSource) +{ + HRESULT hr = S_OK; + ComPtr spTypeHandler; + ComPtr attrs; + + AsWeak(pSource, &_wpSource); + + // Initialize media type and set the video output media type. + CHECKHR_GOTO(MFCreateMediaType(&_spMediaType), done); + _spMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); + _spMediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32); + _spMediaType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive); + _spMediaType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE); + MFSetAttributeSize(_spMediaType.Get(), MF_MT_FRAME_SIZE, NUM_IMAGE_COLS, NUM_IMAGE_ROWS); + MFSetAttributeRatio(_spMediaType.Get(), MF_MT_FRAME_RATE, 30, 1); + MFSetAttributeRatio(_spMediaType.Get(), MF_MT_PIXEL_ASPECT_RATIO, 1, 1); + + CHECKHR_GOTO(MFCreateAttributes(&_spAttributes, 10), done); + CHECKHR_GOTO(this->_SetStreamAttributes(_spAttributes.Get()), done); + CHECKHR_GOTO(MFCreateEventQueue(&_spEventQueue), done); + + // Initialize stream descriptors + CHECKHR_GOTO(MFCreateStreamDescriptor(0, 1, _spMediaType.GetAddressOf(), &_spStreamDesc), done); + + CHECKHR_GOTO(_spStreamDesc->GetMediaTypeHandler(&spTypeHandler), done); + CHECKHR_GOTO(spTypeHandler->SetCurrentMediaType(_spMediaType.Get()), done); + CHECKHR_GOTO(this->_SetStreamDescriptorAttributes(_spStreamDesc.Get()), done); + +done: + return hr; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// IMFMediaEventGenerator +IFACEMETHODIMP SimpleMediaStream::BeginGetEvent(IMFAsyncCallback *pCallback, IUnknown *punkState) +{ + auto lock = _critSec.Lock(); + + HRESULT hr = _CheckShutdownRequiresLock(); + + if (SUCCEEDED(hr)) + { + hr = _spEventQueue->BeginGetEvent(pCallback, punkState); + } + + return hr; +} + +IFACEMETHODIMP SimpleMediaStream::EndGetEvent(IMFAsyncResult *pResult, IMFMediaEvent **ppEvent) +{ + auto lock = _critSec.Lock(); + + HRESULT hr = _CheckShutdownRequiresLock(); + + if (SUCCEEDED(hr)) + { + hr = _spEventQueue->EndGetEvent(pResult, ppEvent); + } + + return hr; +} + +IFACEMETHODIMP SimpleMediaStream::GetEvent(DWORD dwFlags, IMFMediaEvent **ppEvent) +{ + // NOTE: + // GetEvent can block indefinitely, so we don't hold the lock. + // This requires some juggling with the event queue pointer. + + HRESULT hr = S_OK; + + ComPtr spQueue; + + { + auto lock = _critSec.Lock(); + + // Check shutdown + hr = _CheckShutdownRequiresLock(); + + if (SUCCEEDED(hr)) + { + spQueue = _spEventQueue; + } + } + + // Now get the event. + if (SUCCEEDED(hr)) + { + hr = spQueue->GetEvent(dwFlags, ppEvent); + } + + return hr; +} + +IFACEMETHODIMP SimpleMediaStream::QueueEvent(MediaEventType met, REFGUID guidExtendedType, HRESULT hrStatus, const PROPVARIANT *pvValue) +{ + auto lock = _critSec.Lock(); + + HRESULT hr = _CheckShutdownRequiresLock(); + if (SUCCEEDED(hr)) + { + hr = _spEventQueue->QueueEventParamVar(met, guidExtendedType, hrStatus, pvValue); + } + + return hr; +} + +////////////////////////////////////////////////////////////////////////////////////////// +// IMFMediaStream +IFACEMETHODIMP SimpleMediaStream::GetMediaSource(IMFMediaSource **ppMediaSource) +{ + if (ppMediaSource == nullptr) + { + return E_POINTER; + } + *ppMediaSource = nullptr; + + auto lock = _critSec.Lock(); + HRESULT hr = _CheckShutdownRequiresLock(); + + if (SUCCEEDED(hr)) + { + ComPtr spSource; + _wpSource.As(&spSource); + if (spSource != nullptr) + { + hr = spSource->QueryInterface(IID_PPV_ARGS(ppMediaSource)); + } + else + { + hr = E_UNEXPECTED; + } + } + + return hr; +} + +IFACEMETHODIMP SimpleMediaStream::GetStreamDescriptor(IMFStreamDescriptor **ppStreamDescriptor) +{ + if (ppStreamDescriptor == nullptr) + { + return E_POINTER; + } + + *ppStreamDescriptor = nullptr; + + auto lock = _critSec.Lock(); + HRESULT hr = _CheckShutdownRequiresLock(); + + if (SUCCEEDED(hr)) + { + if (_spStreamDesc != nullptr) + { + *ppStreamDescriptor = _spStreamDesc.Get(); + (*ppStreamDescriptor)->AddRef(); + } + else + { + return E_UNEXPECTED; + } + } + + return hr; +} + +/* + Writes to a buffer representing a 2D image. + Writes a different constant to each line based on row number and current time. + + Assumes top down image, no negative stride and pBuf points to the begnning of the buffer of length len. + + Param: + pBuf - pointer to beginning of buffer + pitch - line length in bytes + len - length of buffer in bytes +*/ +HRESULT WriteSampleData(BYTE *pBuf, LONG pitch, DWORD len) +{ + if (pBuf == nullptr) + { + return E_POINTER; + } + + const int NUM_ROWS = len / abs(pitch); + + LONGLONG curSysTimeInS = MFGetSystemTime() / (MFTIME)10000000; + int offset = curSysTimeInS % NUM_ROWS; + + for (int r = 0; r < NUM_ROWS; r++) + { + int grayColor = r + offset; + memset(pBuf + (pitch * r), (BYTE)(grayColor % NUM_ROWS), pitch); + } + + return S_OK; +} + +IFACEMETHODIMP SimpleMediaStream::RequestSample(IUnknown *pToken) +{ + auto lock = _critSec.Lock(); + + HRESULT hr = _CheckShutdownRequiresLock(); + + if (SUCCEEDED(hr)) + { + ComPtr spSample; + + ComPtr spOutputBuffer; + hr = MFCreate2DMediaBuffer(NUM_IMAGE_COLS, NUM_IMAGE_ROWS, D3DFMT_X8R8G8B8, false, &spOutputBuffer); + + LONG pitch = IMAGE_ROW_SIZE_BYTES; + BYTE *bufferStart = nullptr; // not used, since in this example we know the image will be top down, so bufferStart == pBuf + DWORD bufferLength = IMAGE_BUFFER_SIZE_BYTES; + + BYTE *pBuf = nullptr; + ComPtr spBuffer2D; + if (SUCCEEDED(hr)) + { + hr = spOutputBuffer.As(&spBuffer2D); + } + + if (SUCCEEDED(hr)) + { + if (spBuffer2D != nullptr) + { + hr = spBuffer2D->Lock2DSize(MF2DBuffer_LockFlags_Write, &pBuf, &pitch, &bufferStart, &bufferLength); + } + else + { + hr = spOutputBuffer->Lock(&pBuf, nullptr, nullptr); + } + } + + if (SUCCEEDED(hr)) + { + hr = WriteSampleData(pBuf, pitch, bufferLength); + } + + if (SUCCEEDED(hr)) + { + hr = spOutputBuffer->SetCurrentLength(bufferLength); + } + + if (SUCCEEDED(hr)) + { + hr = spBuffer2D->Unlock2D(); + } + + if (SUCCEEDED(hr)) + { + hr = MFCreateSample(&spSample); + } + + if (SUCCEEDED(hr)) + { + hr = spSample->AddBuffer(spOutputBuffer.Get()); + } + + // set timestamp + if (SUCCEEDED(hr)) + { + hr = spSample->SetSampleTime(MFGetSystemTime()); + } + if (SUCCEEDED(hr)) + { + hr = spSample->SetSampleDuration(330000); + } + + if (pToken != nullptr) + { + hr = spSample->SetUnknown(MFSampleExtension_Token, pToken); + } + + if (SUCCEEDED(hr)) + { + hr = _spEventQueue->QueueEventParamUnk(MEMediaSample, GUID_NULL, S_OK, spSample.Get()); + } + } + + return hr; +} + +////////////////////////////////////////////////////////////////////////////////////////// +// IMFMediaStream2 +IFACEMETHODIMP SimpleMediaStream::SetStreamState(MF_STREAM_STATE state) +{ + bool runningState = false; + auto lock = _critSec.Lock(); + + HRESULT hr = S_OK; + + CHECKHR_GOTO(_CheckShutdownRequiresLock(), done); + + switch (state) + { + case MF_STREAM_STATE_PAUSED: + goto done; // because not supported + case MF_STREAM_STATE_RUNNING: + runningState = true; + break; + case MF_STREAM_STATE_STOPPED: + runningState = false; + break; + default: + hr = MF_E_INVALID_STATE_TRANSITION; + break; + } + + _isSelected = runningState; + +done: + return hr; +} + +IFACEMETHODIMP SimpleMediaStream::GetStreamState(_Out_ MF_STREAM_STATE *pState) +{ + auto lock = _critSec.Lock(); + BOOLEAN pauseState = false; + + HRESULT hr = _CheckShutdownRequiresLock(); + + if (SUCCEEDED(hr)) + { + *pState = (_isSelected ? MF_STREAM_STATE_RUNNING : MF_STREAM_STATE_STOPPED); + } + + return hr; +} + +HRESULT SimpleMediaStream::Shutdown() +{ + HRESULT hr = S_OK; + auto lock = _critSec.Lock(); + + _isShutdown = true; + + if (_spEventQueue != nullptr) + { + hr = _spEventQueue->Shutdown(); + _spEventQueue.Reset(); + } + + _spAttributes.Reset(); + _spMediaType.Reset(); + _spStreamDesc.Reset(); + + _isSelected = false; + + _wpSource.Reset(); + + return hr; +} + +HRESULT SimpleMediaStream::_CheckShutdownRequiresLock() +{ + if (_isShutdown) + { + return MF_E_SHUTDOWN; + } + + if (_spEventQueue == nullptr) + { + return E_UNEXPECTED; + + } + return S_OK; +} + +HRESULT SimpleMediaStream::_SetStreamAttributes(IMFAttributes *pAttributeStore) +{ + HRESULT hr = S_OK; + + if (SUCCEEDED(hr)) { hr = pAttributeStore->SetGUID(MF_DEVICESTREAM_STREAM_CATEGORY, PINNAME_VIDEO_CAPTURE); } + if (SUCCEEDED(hr)) { hr = pAttributeStore->SetUINT32(MF_DEVICESTREAM_STREAM_ID, STREAMINDEX); } + if (SUCCEEDED(hr)) { hr = pAttributeStore->SetUINT32(MF_DEVICESTREAM_FRAMESERVER_SHARED, 1); } + + if (SUCCEEDED(hr)) { hr = pAttributeStore->SetUINT32(MF_DEVICESTREAM_ATTRIBUTE_FRAMESOURCE_TYPES, _MFFrameSourceTypes::MFFrameSourceTypes_Color); } + + return hr; +} + +HRESULT SimpleMediaStream::_SetStreamDescriptorAttributes(IMFAttributes *pAttributeStore) +{ + HRESULT hr = S_OK; + + if (SUCCEEDED(hr)) { hr = pAttributeStore->SetGUID(MF_DEVICESTREAM_STREAM_CATEGORY, PINNAME_VIDEO_CAPTURE); } + if (SUCCEEDED(hr)) { hr = pAttributeStore->SetUINT32(MF_DEVICESTREAM_STREAM_ID, STREAMINDEX); } + if (SUCCEEDED(hr)) { hr = pAttributeStore->SetUINT32(MF_DEVICESTREAM_FRAMESERVER_SHARED, 1); } + + if (SUCCEEDED(hr)) { hr = pAttributeStore->SetUINT32(MF_DEVICESTREAM_ATTRIBUTE_FRAMESOURCE_TYPES, _MFFrameSourceTypes::MFFrameSourceTypes_Color); } + + return hr; +} \ No newline at end of file diff --git a/general/SimpleMediaSource/MediaSource/SimpleMediaStream.h b/general/SimpleMediaSource/MediaSource/SimpleMediaStream.h new file mode 100644 index 00000000..b804b1ea --- /dev/null +++ b/general/SimpleMediaSource/MediaSource/SimpleMediaStream.h @@ -0,0 +1,54 @@ +#pragma once + +#include "stdafx.h" +#include "SimpleMediaSource.h" + +class SimpleMediaSource; + +class SimpleMediaStream : public RuntimeClass< + RuntimeClassFlags, + IMFMediaEventGenerator, + IMFMediaStream, + IMFMediaStream2> +{ + friend class SimpleMediaSource; + +public: + // IMFMediaEventGenerator + IFACEMETHOD(BeginGetEvent)(IMFAsyncCallback *pCallback, IUnknown *punkState); + IFACEMETHOD(EndGetEvent)(IMFAsyncResult *pResult, IMFMediaEvent **ppEvent); + IFACEMETHOD(GetEvent)(DWORD dwFlags, IMFMediaEvent **ppEvent); + IFACEMETHOD(QueueEvent)(MediaEventType met, REFGUID guidExtendedType, HRESULT hrStatus, const PROPVARIANT *pvValue); + + // IMFMediaStream + IFACEMETHOD(GetMediaSource)(IMFMediaSource **ppMediaSource); + IFACEMETHOD(GetStreamDescriptor)(IMFStreamDescriptor **ppStreamDescriptor); + IFACEMETHOD(RequestSample)(IUnknown *pToken); + + // IMFMediaStream2 + IFACEMETHOD(SetStreamState)(MF_STREAM_STATE state); + IFACEMETHOD(GetStreamState)(_Out_ MF_STREAM_STATE *pState); + +public: + HRESULT RuntimeClassInitialize(_In_ SimpleMediaSource* pSource); + HRESULT Shutdown(); +private: + HRESULT _CheckShutdownRequiresLock(); + + HRESULT _SetStreamAttributes(IMFAttributes* pAttributeStore); + HRESULT _SetStreamDescriptorAttributes(IMFAttributes* pAttributeStore); +private: + CriticalSection _critSec; + + WeakRef _wpSource; + + ComPtr _spEventQueue; + ComPtr _spAttributes; + ComPtr _spMediaType; + ComPtr _spStreamDesc; + bool _isShutdown = false; + bool _isSelected = false; + + const DWORD STREAMINDEX = 0; // since there is only one stream +}; + diff --git a/general/SimpleMediaSource/MediaSource/dllMain.cpp b/general/SimpleMediaSource/MediaSource/dllMain.cpp new file mode 100644 index 00000000..aed44eb0 --- /dev/null +++ b/general/SimpleMediaSource/MediaSource/dllMain.cpp @@ -0,0 +1,35 @@ +/// +/// Copyright (c) Microsoft Corporation. All rights reserved. +/// +// dllmain.cpp : Defines the entry point for the DLL application. +#include "stdafx.h" + +#include + +#if !defined(__WRL_CLASSIC_COM__) +STDAPI DllGetActivationFactory(_In_ HSTRING activatibleClassId, _COM_Outptr_ IActivationFactory** factory) +{ + return Module::GetModule().GetActivationFactory(activatibleClassId, factory); +} +#endif + +#if !defined(__WRL_WINRT_STRICT__) +STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, _COM_Outptr_ void** ppv) +{ + return Module::GetModule().GetClassObject(rclsid, riid, ppv); +} +#endif + +STDAPI DllCanUnloadNow() +{ + return Module::GetModule().Terminate() ? S_OK : S_FALSE; +} + +STDAPI_(BOOL) DllMain(_In_opt_ HINSTANCE hinst, DWORD reason, _In_opt_ void*) +{ + if (reason == DLL_PROCESS_ATTACH) + { + DisableThreadLibraryCalls(hinst); + } + return TRUE; +} diff --git a/general/SimpleMediaSource/MediaSource/module.def b/general/SimpleMediaSource/MediaSource/module.def new file mode 100644 index 00000000..ddeb3eac --- /dev/null +++ b/general/SimpleMediaSource/MediaSource/module.def @@ -0,0 +1,6 @@ +LIBRARY + +EXPORTS + DllGetActivationFactory PRIVATE + DllGetClassObject PRIVATE + DllCanUnloadNow PRIVATE diff --git a/general/SimpleMediaSource/MediaSource/stdafx.cpp b/general/SimpleMediaSource/MediaSource/stdafx.cpp new file mode 100644 index 00000000..dc97a45b --- /dev/null +++ b/general/SimpleMediaSource/MediaSource/stdafx.cpp @@ -0,0 +1,11 @@ +/// +/// Copyright (c) Microsoft Corporation. All rights reserved. +/// +// stdafx.cpp : source file that includes just the standard includes +// KinectMFMediaSource.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/general/SimpleMediaSource/MediaSource/stdafx.h b/general/SimpleMediaSource/MediaSource/stdafx.h new file mode 100644 index 00000000..4702e47e --- /dev/null +++ b/general/SimpleMediaSource/MediaSource/stdafx.h @@ -0,0 +1,27 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +// Windows Header Files: +#include +#include +#include +#include +//#include // Must be included before , or else DirectDraw GUIDs will be defined twice. See the comment in . +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; \ No newline at end of file diff --git a/general/SimpleMediaSource/SimpleMediaSource.sln b/general/SimpleMediaSource/SimpleMediaSource.sln new file mode 100644 index 00000000..dd03ec69 --- /dev/null +++ b/general/SimpleMediaSource/SimpleMediaSource.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27703.2026 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MediaSource", "MediaSource\MediaSource.vcxproj", "{43AD9BF7-E765-48FE-9826-71A8F2CB12DD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Debug|x64.ActiveCfg = Debug|x64 + {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Debug|x64.Build.0 = Debug|x64 + {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Debug|x86.ActiveCfg = Debug|Win32 + {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Debug|x86.Build.0 = Debug|Win32 + {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Release|x64.ActiveCfg = Release|x64 + {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Release|x64.Build.0 = Release|x64 + {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Release|x86.ActiveCfg = Release|Win32 + {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {2205BF4A-ACC2-4A73-8C1E-C3D9AF0F8B24} + EndGlobalSection +EndGlobal -- cgit v1.3.1 From 58a4f43a0c75285c30ce4806d011553ebc3f563d Mon Sep 17 00:00:00 2001 From: Peihsun Yeh Date: Wed, 1 Aug 2018 17:14:16 -0700 Subject: fix up of media source --- .../MediaSource/MediaSource.vcxproj | 8 +- .../MediaSource/SimpleMediaSource.cpp | 598 +++++++++++---------- .../MediaSource/SimpleMediaSource.h | 87 +-- .../MediaSource/SimpleMediaStream.cpp | 350 ++++++------ .../MediaSource/SimpleMediaStream.h | 14 +- general/SimpleMediaSource/MediaSource/stdafx.h | 57 +- 6 files changed, 559 insertions(+), 555 deletions(-) (limited to 'general/SimpleMediaSource') diff --git a/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj b/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj index b1f8a7f4..da95eecd 100644 --- a/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj +++ b/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj @@ -78,7 +78,7 @@ true - mfplat.lib;RuntimeObject.lib;%(AdditionalDependencies) + mfplat.lib;RuntimeObject.lib;Mfsensorgroup.lib;%(AdditionalDependencies) @@ -89,7 +89,7 @@ true - mfplat.lib;RuntimeObject.lib;%(AdditionalDependencies) + mfplat.lib;RuntimeObject.lib;Mfsensorgroup.lib;%(AdditionalDependencies) @@ -104,7 +104,7 @@ true true - mfplat.lib;RuntimeObject.lib;%(AdditionalDependencies) + mfplat.lib;RuntimeObject.lib;Mfsensorgroup.lib;%(AdditionalDependencies) @@ -119,7 +119,7 @@ true true - mfplat.lib;RuntimeObject.lib;%(AdditionalDependencies) + mfplat.lib;RuntimeObject.lib;Mfsensorgroup.lib;%(AdditionalDependencies) diff --git a/general/SimpleMediaSource/MediaSource/SimpleMediaSource.cpp b/general/SimpleMediaSource/MediaSource/SimpleMediaSource.cpp index 34b6f2e2..1729fbcf 100644 --- a/general/SimpleMediaSource/MediaSource/SimpleMediaSource.cpp +++ b/general/SimpleMediaSource/MediaSource/SimpleMediaSource.cpp @@ -1,72 +1,62 @@ -#include "SimpleMediaSource.h" -#include "SimpleMediaStream.h" +#include "stdafx.h" /////////////////////////////////////////////////////////////////////////////// -HRESULT SimpleMediaSource::RuntimeClassInitialize() +HRESULT +SimpleMediaSource::RuntimeClassInitialize( + ) { HRESULT hr = S_OK; - if (SUCCEEDED(hr)) - { - hr = MFCreateAttributes(&_spAttributes, 10); - } - - if (SUCCEEDED(hr)) - { - hr = MFCreateEventQueue(&_spEventQueue); - } - - if (SUCCEEDED(hr)) - { - hr = MakeAndInitialize(&_stream, this); - } - - if (SUCCEEDED(hr)) + RETURN_IF_FAILED (MFCreateAttributes(&_spAttributes, 10)); + RETURN_IF_FAILED (MFCreateEventQueue(&_spEventQueue)); + RETURN_IF_FAILED (MakeAndInitialize(&_stream, this)); { ComPtr streamDescriptor(_stream.Get()->_spStreamDesc.Get()); - hr = MFCreatePresentationDescriptor(NUM_STREAMS, streamDescriptor.GetAddressOf(), &_spPresentationDescriptor); + RETURN_IF_FAILED (MFCreatePresentationDescriptor(NUM_STREAMS, streamDescriptor.GetAddressOf(), &_spPresentationDescriptor)); } - if (SUCCEEDED(hr)) - { - _wasStreamPreviouslySelected = false; - _sourceState = SourceState::Stopped; - } + _wasStreamPreviouslySelected = false; + _sourceState = SourceState::Stopped; return hr; } // IMFMediaEventGenerator methods. -/////////////////////////////////////////////////////////////////////////////// -IFACEMETHODIMP SimpleMediaSource::BeginGetEvent(IMFAsyncCallback *pCallback, IUnknown *punkState) +IFACEMETHODIMP +SimpleMediaSource::BeginGetEvent( + _In_ IMFAsyncCallback *pCallback, + _In_ IUnknown *punkState + ) { + HRESULT hr = S_OK; auto lock = _critSec.Lock(); - HRESULT hr = _CheckShutdownRequiresLock(); - if (SUCCEEDED(hr)) - { - hr = _spEventQueue->BeginGetEvent(pCallback, punkState); - } + RETURN_IF_FAILED (_CheckShutdownRequiresLock()); + RETURN_IF_FAILED (_spEventQueue->BeginGetEvent(pCallback, punkState)); return hr; } -/////////////////////////////////////////////////////////////////////////////// -IFACEMETHODIMP SimpleMediaSource::EndGetEvent(IMFAsyncResult *pResult, IMFMediaEvent **ppEvent) +IFACEMETHODIMP +SimpleMediaSource::EndGetEvent( + _In_ IMFAsyncResult *pResult, + _COM_Outptr_ IMFMediaEvent **ppEvent + ) { + HRESULT hr = S_OK; auto lock = _critSec.Lock(); - HRESULT hr = _CheckShutdownRequiresLock(); - if (SUCCEEDED(hr)) - { - hr = _spEventQueue->EndGetEvent(pResult, ppEvent); - } + RETURN_IF_FAILED (_CheckShutdownRequiresLock()); + RETURN_IF_FAILED (_spEventQueue->EndGetEvent(pResult, ppEvent)); return hr; } -/////////////////////////////////////////////////////////////////////////////// -IFACEMETHODIMP SimpleMediaSource::GetEvent(DWORD dwFlags, IMFMediaEvent **ppEvent) +IFACEMETHODIMP +SimpleMediaSource::GetEvent( + DWORD dwFlags, + _COM_Outptr_ IMFMediaEvent **ppEvent + ) { // NOTE: // GetEvent can block indefinitely, so we don't hold the lock. @@ -79,369 +69,398 @@ IFACEMETHODIMP SimpleMediaSource::GetEvent(DWORD dwFlags, IMFMediaEvent **ppEven { auto lock = _critSec.Lock(); - hr = _CheckShutdownRequiresLock(); - if (SUCCEEDED(hr)) - { - spQueue = _spEventQueue; - } + RETURN_IF_FAILED (_CheckShutdownRequiresLock()); + spQueue = _spEventQueue; } // Now get the event. - if (SUCCEEDED(hr)) - { - hr = spQueue->GetEvent(dwFlags, ppEvent); - } + RETURN_IF_FAILED (_spEventQueue->GetEvent(dwFlags, ppEvent)); return hr; } -/////////////////////////////////////////////////////////////////////////////// -IFACEMETHODIMP SimpleMediaSource::QueueEvent( +IFACEMETHODIMP +SimpleMediaSource::QueueEvent( MediaEventType eventType, REFGUID guidExtendedType, HRESULT hrStatus, - _In_opt_ PROPVARIANT const *pvValue) + _In_opt_ PROPVARIANT const *pvValue + ) { + HRESULT hr = S_OK; auto lock = _critSec.Lock(); - HRESULT hr = _CheckShutdownRequiresLock(); - if (SUCCEEDED(hr)) - { - hr = _spEventQueue->QueueEventParamVar(eventType, guidExtendedType, hrStatus, pvValue); - } + RETURN_IF_FAILED (_CheckShutdownRequiresLock()); + RETURN_IF_FAILED (_spEventQueue->QueueEventParamVar(eventType, guidExtendedType, hrStatus, pvValue)); return hr; } // IMFMediaSource methods -/////////////////////////////////////////////////////////////////////////////// -IFACEMETHODIMP SimpleMediaSource::CreatePresentationDescriptor( - IMFPresentationDescriptor **ppPresentationDescriptor) +IFACEMETHODIMP +SimpleMediaSource::CreatePresentationDescriptor( + _COM_Outptr_ IMFPresentationDescriptor **ppPresentationDescriptor + ) { + HRESULT hr = S_OK; + auto lock = _critSec.Lock(); + if (ppPresentationDescriptor == nullptr) { return E_POINTER; } - *ppPresentationDescriptor = nullptr; - auto lock = _critSec.Lock(); - - HRESULT hr = _CheckShutdownRequiresLock(); - if (SUCCEEDED(hr)) - { - hr = _spPresentationDescriptor->Clone(ppPresentationDescriptor); - } + RETURN_IF_FAILED (_CheckShutdownRequiresLock()); + RETURN_IF_FAILED (_spPresentationDescriptor->Clone(ppPresentationDescriptor)); return hr; } -/////////////////////////////////////////////////////////////////////////////// -IFACEMETHODIMP SimpleMediaSource::GetCharacteristics(DWORD *pdwCharacteristics) +IFACEMETHODIMP +SimpleMediaSource::GetCharacteristics( + _Out_ DWORD *pdwCharacteristics + ) { - *pdwCharacteristics = 0; - + HRESULT hr = S_OK; auto lock = _critSec.Lock(); - HRESULT hr = _CheckShutdownRequiresLock(); - if (SUCCEEDED(hr)) + if (nullptr == pdwCharacteristics) { - *pdwCharacteristics = MFMEDIASOURCE_IS_LIVE; + return E_POINTER; } + *pdwCharacteristics = 0; + + RETURN_IF_FAILED (_CheckShutdownRequiresLock()); + *pdwCharacteristics = MFMEDIASOURCE_IS_LIVE; return hr; } -/////////////////////////////////////////////////////////////////////////////// -IFACEMETHODIMP SimpleMediaSource::Pause() +IFACEMETHODIMP +SimpleMediaSource::Pause( + ) { - // Pause() not required/needed for live sources - HRESULT hr = MF_E_INVALID_STATE_TRANSITION; - - return hr; + // Pause() not required/needed + return MF_E_INVALID_STATE_TRANSITION; } -/////////////////////////////////////////////////////////////////////////////// -IFACEMETHODIMP SimpleMediaSource::Shutdown() + +IFACEMETHODIMP +SimpleMediaSource::Shutdown( + ) { HRESULT hr = S_OK; - { - auto lock = _critSec.Lock(); + auto lock = _critSec.Lock(); - _sourceState = SourceState::Shutdown; + _sourceState = SourceState::Shutdown; - _spAttributes.Reset(); - _spPresentationDescriptor.Reset(); + _spAttributes.Reset(); + _spPresentationDescriptor.Reset(); - if (_spEventQueue != nullptr) - { - _spEventQueue->Shutdown(); - _spEventQueue.Reset(); - } + if (_spEventQueue != nullptr) + { + _spEventQueue->Shutdown(); + _spEventQueue.Reset(); + } - if (_stream != nullptr) - { - _stream.Get()->Shutdown(); - _stream.Reset(); - } + if (_stream != nullptr) + { + _stream.Get()->Shutdown(); + _stream.Reset(); } + return hr; } -/////////////////////////////////////////////////////////////////////////////// -IFACEMETHODIMP SimpleMediaSource::Start( +IFACEMETHODIMP +SimpleMediaSource::Start( _In_ IMFPresentationDescriptor *pPresentationDescriptor, _In_opt_ const GUID *pguidTimeFormat, - _In_ const PROPVARIANT *pvarStartPos) + _In_ const PROPVARIANT *pvarStartPos + ) { HRESULT hr = S_OK; + auto lock = _critSec.Lock(); + DWORD count = 0; + PROPVARIANT startTime; + BOOL selected = false; + ComPtr streamDesc; + DWORD streamIndex = 0; if (pPresentationDescriptor == nullptr || pvarStartPos == nullptr) { - hr = E_INVALIDARG; + return E_INVALIDARG; } else if (pguidTimeFormat != nullptr && *pguidTimeFormat != GUID_NULL) { - hr = MF_E_UNSUPPORTED_TIME_FORMAT; + return MF_E_UNSUPPORTED_TIME_FORMAT; } - do - { - BREAK_ON_FAIL(hr); - - auto lock = _critSec.Lock(); - BREAK_ON_FAIL(hr = _CheckShutdownRequiresLock()); - - if (_sourceState != SourceState::Stopped) - { - hr = MF_E_INVALID_STATE_TRANSITION; - break; - } - - _sourceState = SourceState::Started; - - // This checks the passed in PresentationDescriptor matches the member of streams we - // have defined internally and that at least one stream is selected - BREAK_ON_FAIL(hr = _ValidatePresentationDescriptor(pPresentationDescriptor)); - - DWORD count = 0; - BREAK_ON_FAIL(hr = pPresentationDescriptor->GetStreamDescriptorCount(&count)); - - PROPVARIANT startTime; - BREAK_ON_FAIL(hr = InitPropVariantFromInt64(MFGetSystemTime(), &startTime)); - - // Send event that the source started. Include error code in case it failed. - BREAK_ON_FAIL(hr = _spEventQueue->QueueEventParamVar(MESourceStarted, GUID_NULL, hr, &startTime)); - - // Open and un-pause the selected stream(s) - BOOL selected = false; - ComPtr spStreamDescriptor; - BREAK_ON_FAIL(hr = pPresentationDescriptor->GetStreamDescriptorByIndex(0, &selected, &spStreamDescriptor)); - - DWORD streamIndex = 0; - BREAK_ON_FAIL(hr = spStreamDescriptor->GetStreamIdentifier(&streamIndex)); - - if (streamIndex >= NUM_STREAMS) - { - hr = MF_E_INVALIDSTREAMNUMBER; - break; - } - - if (selected) - { - // Update our internal PresentationDescriptor - BREAK_ON_FAIL(hr = _spPresentationDescriptor->SelectStream(streamIndex)); - BREAK_ON_FAIL(hr = _stream.Get()->SetStreamState(MF_STREAM_STATE_RUNNING)); + RETURN_IF_FAILED (_CheckShutdownRequiresLock()); - ComPtr spunkStream; - BREAK_ON_FAIL(hr = _stream.As(&spunkStream)); + if (_sourceState != SourceState::Stopped) + { + return MF_E_INVALID_STATE_TRANSITION; + } - BREAK_ON_FAIL(hr = _spEventQueue->QueueEventParamUnk(_wasStreamPreviouslySelected ? MEUpdatedStream : MENewStream, - GUID_NULL, S_OK, spunkStream.Get())); - BREAK_ON_FAIL(hr = _stream.Get()->QueueEvent(MEStreamStarted, GUID_NULL, S_OK, &startTime)); - } - _wasStreamPreviouslySelected = selected; + _sourceState = SourceState::Started; + + // This checks the passed in PresentationDescriptor matches the member of streams we + // have defined internally and that at least one stream is selected + RETURN_IF_FAILED (_ValidatePresentationDescriptor(pPresentationDescriptor)); + RETURN_IF_FAILED (pPresentationDescriptor->GetStreamDescriptorCount(&count)); + RETURN_IF_FAILED (InitPropVariantFromInt64(MFGetSystemTime(), &startTime)); + + // Send event that the source started. Include error code in case it failed. + RETURN_IF_FAILED (_spEventQueue->QueueEventParamVar(MESourceStarted, + GUID_NULL, + hr, + &startTime)); + + // We're hardcoding this to the first descriptor + // since this sample is a single stream sample. For + // multiple streams, we need to walk the list of streams + // and for each selected stream, send the MEUpdatedStream + // or MENewStream event along with the MEStreamStarted + // event. + RETURN_IF_FAILED (pPresentationDescriptor->GetStreamDescriptorByIndex(0, + &selected, + &streamDesc)); + RETURN_IF_FAILED (streamDesc->GetStreamIdentifier(&streamIndex)); + if (streamIndex >= NUM_STREAMS) + { + return MF_E_INVALIDSTREAMNUMBER; + } - } while (false); + if (selected) + { + ComPtr spunkStream; + MediaEventType met = (_wasStreamPreviouslySelected ? MEUpdatedStream : MENewStream); + + // Update our internal PresentationDescriptor + RETURN_IF_FAILED (_spPresentationDescriptor->SelectStream(streamIndex)); + RETURN_IF_FAILED (_stream.Get()->SetStreamState(MF_STREAM_STATE_RUNNING)); + RETURN_IF_FAILED (_stream.As(&spunkStream)); + + // Send the MEUpdatedStream/MENewStream to our source event + // queue. + RETURN_IF_FAILED (_spEventQueue->QueueEventParamUnk(met, + GUID_NULL, + S_OK, + spunkStream.Get())); + + // But for our stream started (MEStreamStarted), we post to our + // stream event queue. + RETURN_IF_FAILED (_stream.Get()->QueueEvent(MEStreamStarted, + GUID_NULL, + S_OK, + &startTime)); + } + _wasStreamPreviouslySelected = selected; return hr; } -/////////////////////////////////////////////////////////////////////////////// -IFACEMETHODIMP SimpleMediaSource::Stop() +IFACEMETHODIMP +SimpleMediaSource::Stop( + ) { HRESULT hr = S_OK; + auto lock = _critSec.Lock(); + PROPVARIANT stopTime; + DWORD count = 0; + MF_STREAM_STATE state; - do + if (_sourceState != SourceState::Started) { - auto lock = _critSec.Lock(); - - if (_sourceState != SourceState::Started) - { - BREAK_ON_FAIL(hr = MF_E_INVALID_STATE_TRANSITION); - } - - BREAK_ON_FAIL(hr = _CheckShutdownRequiresLock()); - - PROPVARIANT stopTime; - BREAK_ON_FAIL(hr = InitPropVariantFromInt64(MFGetSystemTime(), &stopTime)); - - DWORD count = 0; - BREAK_ON_FAIL(hr = _spPresentationDescriptor->GetStreamDescriptorCount(&count)); - // Deselect the streams and send the stream stopped events. - MF_STREAM_STATE state; - hr = _stream.Get()->GetStreamState(&state); - if (FAILED(hr)) - { - continue; - } - _wasStreamPreviouslySelected = (state == MF_STREAM_STATE_RUNNING); - hr = _stream.Get()->SetStreamState(MF_STREAM_STATE_STOPPED); - if (FAILED(hr)) - { - continue; - } - _spPresentationDescriptor->DeselectStream(0); - hr = _stream.Get()->QueueEvent(MEStreamStopped, GUID_NULL, hr, &stopTime); - if (FAILED(hr)) - { - continue; - } + return MF_E_INVALID_STATE_TRANSITION; + } - BREAK_ON_FAIL(hr = _spEventQueue->QueueEventParamVar(MESourceStopped, GUID_NULL, hr, &stopTime)); + RETURN_IF_FAILED (_CheckShutdownRequiresLock()); + RETURN_IF_FAILED (InitPropVariantFromInt64(MFGetSystemTime(), &stopTime)); + RETURN_IF_FAILED (_spPresentationDescriptor->GetStreamDescriptorCount(&count)); - } while (false); + // Deselect the streams and send the stream stopped events. + RETURN_IF_FAILED (_stream.Get()->GetStreamState(&state)); + _wasStreamPreviouslySelected = (state == MF_STREAM_STATE_RUNNING); + RETURN_IF_FAILED (_stream.Get()->SetStreamState(MF_STREAM_STATE_STOPPED)); + _spPresentationDescriptor->DeselectStream(0); + RETURN_IF_FAILED (_stream.Get()->QueueEvent(MEStreamStopped, GUID_NULL, hr, &stopTime)); + RETURN_IF_FAILED (_spEventQueue->QueueEventParamVar(MESourceStopped, GUID_NULL, hr, &stopTime)); return hr; } // IMFMediaSourceEx -/////////////////////////////////////////////////////////////////////////////// -IFACEMETHODIMP SimpleMediaSource::GetSourceAttributes(_Outptr_ IMFAttributes **ppAttributes) +IFACEMETHODIMP +SimpleMediaSource::GetSourceAttributes( + _COM_Outptr_ IMFAttributes** sourceAttributes + ) { - if (ppAttributes == nullptr) + HRESULT hr = S_OK; + auto lock = _critSec.Lock(); + + if (nullptr == sourceAttributes) { return E_POINTER; } - auto lock = _critSec.Lock(); + RETURN_IF_FAILED (_CheckShutdownRequiresLock()); - HRESULT hr = _CheckShutdownRequiresLock(); - if (SUCCEEDED(hr)) + *sourceAttributes = nullptr; + if (_spAttributes.Get() == nullptr) { - *ppAttributes = _spAttributes.Get(); - (*ppAttributes)->AddRef(); - } - else - { - hr = E_UNEXPECTED; + ComPtr profileCollection; + ComPtr profile; + + // Create our source attribute store. + RETURN_IF_FAILED (MFCreateAttributes(_spAttributes.GetAddressOf(), 1)); + + // Create an empty profile collection... + RETURN_IF_FAILED (MFCreateSensorProfileCollection(&profileCollection)); + + // In this example since we have just one stream, we only have one + // pin to add: Pin0. + + // Legacy profile is mandatory. This is to ensure non-profile + // aware applications can still function, but with degraded + // feature sets. + RETURN_IF_FAILED (MFCreateSensorProfile(KSCAMERAPROFILE_Legacy, 0, nullptr, + profile.ReleaseAndGetAddressOf())); + RETURN_IF_FAILED (profile->AddProfileFilter(0, L"((RES==;FRT<=30,1;SUT==))")); + RETURN_IF_FAILED (profileCollection->AddProfile(profile.Get())); + + // High Frame Rate profile will only allow >=60fps. + RETURN_IF_FAILED (MFCreateSensorProfile(KSCAMERAPROFILE_HighFrameRate, 0, nullptr, + profile.ReleaseAndGetAddressOf())); + RETURN_IF_FAILED (profile->AddProfileFilter(0, L"((RES==;FRT>=60,1;SUT==))")); + RETURN_IF_FAILED (profileCollection->AddProfile(profile.Get())); + + + // Se the profile collection to the attribute store of the IMFTransform. + RETURN_IF_FAILED (_spAttributes->SetUnknown(MF_DEVICEMFT_SENSORPROFILE_COLLECTION, + profileCollection.Get())); } - return hr; + return _spAttributes.CopyTo(sourceAttributes); } -/////////////////////////////////////////////////////////////////////////////// -IFACEMETHODIMP SimpleMediaSource::GetStreamAttributes(DWORD dwStreamIdentifier, _Outptr_ IMFAttributes **ppAttributes) + +IFACEMETHODIMP +SimpleMediaSource::GetStreamAttributes( + DWORD dwStreamIdentifier, + _COM_Outptr_ IMFAttributes **ppAttributes + ) { + HRESULT hr = S_OK; + auto lock = _critSec.Lock(); + if (ppAttributes == nullptr) { return E_POINTER; } - - auto lock = _critSec.Lock(); - *ppAttributes = nullptr; - HRESULT hr = _CheckShutdownRequiresLock(); - if (SUCCEEDED(hr)) + RETURN_IF_FAILED (_CheckShutdownRequiresLock()); + if (dwStreamIdentifier >= NUM_STREAMS) { - if (dwStreamIdentifier >= NUM_STREAMS) - { - hr = MF_E_INVALIDSTREAMNUMBER; - } - else - { - *ppAttributes = _stream.Get()->_spAttributes.Get(); - (*ppAttributes)->AddRef(); - } + return MF_E_INVALIDSTREAMNUMBER; } else { - hr = E_UNEXPECTED; + *ppAttributes = _stream.Get()->_spAttributes.Get(); + (*ppAttributes)->AddRef(); } return hr; } -/////////////////////////////////////////////////////////////////////////////// -IFACEMETHODIMP SimpleMediaSource::SetD3DManager(_In_opt_ IUnknown* /*pManager*/) +IFACEMETHODIMP +SimpleMediaSource::SetD3DManager( + _In_opt_ IUnknown* /*pManager*/ + ) { - // No need to implement this method in our case. - HRESULT hr = E_NOTIMPL; - return hr; + // Return code is ignored by the frame work, this is a + // best effort attempt to inform the media source of the + // DXGI manager to use if DX surface support is available. + + return E_NOTIMPL; } // IMFGetService methods -/////////////////////////////////////////////////////////////////////////////// _Use_decl_annotations_ -IFACEMETHODIMP SimpleMediaSource::GetService(REFGUID guidService, REFIID riid, LPVOID * ppvObject) +IFACEMETHODIMP +SimpleMediaSource::GetService( + _In_ REFGUID guidService, + _In_ REFIID riid, + _Out_ LPVOID * ppvObject + ) { - HRESULT hr = _CheckShutdownRequiresLock(); - if (SUCCEEDED(hr)) - { - if (!ppvObject) - { - hr = E_INVALIDARG; - } - else - { - *ppvObject = NULL; - } + HRESULT hr = S_OK; + auto lock = _critSec.Lock(); + + RETURN_IF_FAILED (_CheckShutdownRequiresLock()); - hr = MF_E_UNSUPPORTED_SERVICE; + if (!ppvObject) + { + return E_POINTER; } + *ppvObject = NULL; - return hr; + // We have no supported service, just return + // MF_E_UNSUPPORTED_SERVICE for all calls. + + return MF_E_UNSUPPORTED_SERVICE; } // IKsControl methods _Use_decl_annotations_ -IFACEMETHODIMP SimpleMediaSource::KsProperty( - PKSPROPERTY pProperty, - ULONG ulPropertyLength, - LPVOID pPropertyData, - ULONG ulDataLength, - ULONG* pBytesReturned) +IFACEMETHODIMP +SimpleMediaSource::KsProperty( + _In_reads_bytes_(ulPropertyLength) PKSPROPERTY pProperty, + _In_ ULONG ulPropertyLength, + _Inout_updates_to_(ulDataLength, *pBytesReturned) LPVOID pPropertyData, + _In_ ULONG ulDataLength, + _Out_ ULONG* pBytesReturned + ) { - return E_NOTIMPL; + // ERROR_SET_NOT_FOUND is the standard error code returned + // by the AV Stream driver framework when a miniport + // driver does not register a handler for a KS operation. + // We want to mimic the driver behavior here if we don't + // support controls. + return HRESULT_FROM_WIN32(ERROR_SET_NOT_FOUND); } -/////////////////////////////////////////////////////////////////////////////// _Use_decl_annotations_ IFACEMETHODIMP SimpleMediaSource::KsMethod( - PKSMETHOD pMethod, - ULONG ulMethodLength, - LPVOID pMethodData, - ULONG ulDataLength, - ULONG* pBytesReturned) + _In_reads_bytes_(ulMethodLength) PKSMETHOD pMethod, + _In_ ULONG ulMethodLength, + _Inout_updates_to_(ulDataLength, *pBytesReturned) LPVOID pMethodData, + _In_ ULONG ulDataLength, + _Out_ ULONG* pBytesReturned + ) { - return E_NOTIMPL; + return HRESULT_FROM_WIN32(ERROR_SET_NOT_FOUND); } -/////////////////////////////////////////////////////////////////////////////// _Use_decl_annotations_ IFACEMETHODIMP SimpleMediaSource::KsEvent( - _In_opt_ PKSEVENT pEvent, + _In_reads_bytes_opt_(ulEventLength) PKSEVENT pEvent, _In_ ULONG ulEventLength, - _Inout_opt_ LPVOID pEventData, + _Inout_updates_to_(ulDataLength, *pBytesReturned) LPVOID pEventData, _In_ ULONG ulDataLength, - _Out_opt_ ULONG* pBytesReturned) + _Out_opt_ ULONG* pBytesReturned + ) { - return E_NOTIMPL; + return HRESULT_FROM_WIN32(ERROR_SET_NOT_FOUND); } -/////////////////////////////////////////////////////////////////////////////// -HRESULT SimpleMediaSource::_CheckShutdownRequiresLock() +/// Internal methods. +HRESULT +SimpleMediaSource::_CheckShutdownRequiresLock( + ) { if (_sourceState == SourceState::Shutdown) { @@ -456,51 +475,50 @@ HRESULT SimpleMediaSource::_CheckShutdownRequiresLock() return S_OK; } -/////////////////////////////////////////////////////////////////////////////// -HRESULT SimpleMediaSource::_ValidatePresentationDescriptor(IMFPresentationDescriptor *pPD) +HRESULT +SimpleMediaSource::_ValidatePresentationDescriptor( + _In_ IMFPresentationDescriptor *pPD + ) { + HRESULT hr = S_OK; + DWORD cStreams = 0; + bool anySelected = false; + if (pPD == nullptr) { return E_INVALIDARG; } - HRESULT hr = S_OK; - DWORD cStreams = 0; - bool anySelected = false; - // The caller's PD must have the same number of streams as ours. - hr = pPD->GetStreamDescriptorCount(&cStreams); - + RETURN_IF_FAILED (pPD->GetStreamDescriptorCount(&cStreams)); if (SUCCEEDED(hr) && (cStreams != NUM_STREAMS)) { - hr = E_INVALIDARG; + return E_INVALIDARG; } // The caller must select at least one stream. - for (UINT32 i = 0; SUCCEEDED(hr) && i < cStreams; ++i) + for (UINT32 i = 0; i < cStreams; ++i) { ComPtr spSD; BOOL fSelected = FALSE; - hr = pPD->GetStreamDescriptorByIndex(i, &fSelected, &spSD); + DWORD dwId = 0; - if (SUCCEEDED(hr)) - { - anySelected |= !!fSelected; + RETURN_IF_FAILED (pPD->GetStreamDescriptorByIndex(i, &fSelected, &spSD)); - DWORD dwId = 0; - hr = spSD->GetStreamIdentifier(&dwId); + anySelected |= !!fSelected; - if (SUCCEEDED(hr) && dwId >= NUM_STREAMS) - { - hr = E_INVALIDARG; - } + RETURN_IF_FAILED (spSD->GetStreamIdentifier(&dwId)); + if (dwId >= NUM_STREAMS) + { + return E_INVALIDARG; } } if (!anySelected) { - hr = E_INVALIDARG; + return E_INVALIDARG; } return hr; -} \ No newline at end of file +} + diff --git a/general/SimpleMediaSource/MediaSource/SimpleMediaSource.h b/general/SimpleMediaSource/MediaSource/SimpleMediaSource.h index 85b9227f..019926c8 100644 --- a/general/SimpleMediaSource/MediaSource/SimpleMediaSource.h +++ b/general/SimpleMediaSource/MediaSource/SimpleMediaSource.h @@ -3,43 +3,6 @@ // Represents a simple media source that only has one stream and outputs a static image #include "stdafx.h" -#include "SimpleMediaStream.h" - -#define BREAK_ON_FAIL(value) if FAILED(value) break; - -#if !defined(_IKsControl_) -#define _IKsControl_ -interface DECLSPEC_UUID("28F54685-06FD-11D2-B27A-00A0C9223196") IKsControl; -#undef INTERFACE -#define INTERFACE IKsControl -DECLARE_INTERFACE_(IKsControl, IUnknown) -{ - STDMETHOD(KsProperty)( - THIS_ - IN PKSPROPERTY Property, - IN ULONG PropertyLength, - IN OUT LPVOID PropertyData, - IN ULONG DataLength, - OUT ULONG* BytesReturned - ) PURE; - STDMETHOD(KsMethod)( - THIS_ - IN PKSMETHOD Method, - IN ULONG MethodLength, - IN OUT LPVOID MethodData, - IN ULONG DataLength, - OUT ULONG* BytesReturned - ) PURE; - STDMETHOD(KsEvent)( - THIS_ - IN PKSEVENT Event OPTIONAL, - IN ULONG EventLength, - IN OUT LPVOID EventData, - IN ULONG DataLength, - OUT ULONG* BytesReturned - ) PURE; -}; -#endif //!defined(_IKsControl_) class SimpleMediaStream; @@ -70,49 +33,39 @@ public: IFACEMETHOD(GetCharacteristics)(_Out_ DWORD *pdwCharacteristics); IFACEMETHOD(Pause)(); IFACEMETHOD(Shutdown)(); - IFACEMETHOD(Start)( - _In_ IMFPresentationDescriptor *pPresentationDescriptor, - _In_ const GUID *pguidTimeFormat, - _In_ const PROPVARIANT *pvarStartPosition); + IFACEMETHOD(Start)(_In_ IMFPresentationDescriptor *pPresentationDescriptor, _In_ const GUID *pguidTimeFormat, _In_ const PROPVARIANT *pvarStartPosition); IFACEMETHOD(Stop)(); // IMFMediaSourceEx - IFACEMETHOD(GetSourceAttributes)(_Outptr_ IMFAttributes **ppAttributes); - IFACEMETHOD(GetStreamAttributes)(DWORD dwStreamIdentifier, _Outptr_ IMFAttributes **ppAttributes); + IFACEMETHOD(GetSourceAttributes)(_COM_Outptr_ IMFAttributes **ppAttributes); + IFACEMETHOD(GetStreamAttributes)(DWORD dwStreamIdentifier, _COM_Outptr_ IMFAttributes **ppAttributes); IFACEMETHOD(SetD3DManager)(_In_opt_ IUnknown *pManager); // IMFGetService - IFACEMETHOD(GetService)(REFGUID guidService, REFIID riid, _Out_opt_ LPVOID *ppvObject); + IFACEMETHOD(GetService)(_In_ REFGUID guidService, _In_ REFIID riid, _Out_ LPVOID *ppvObject); // IKsControl - IFACEMETHOD(KsProperty)( - _In_ PKSPROPERTY pProperty, - ULONG ulPropertyLength, - _Inout_ LPVOID pPropertyData, - ULONG ulDataLength, - _Out_ ULONG* pBytesReturned); - - IFACEMETHOD(KsMethod)( - _In_ PKSMETHOD pMethod, - ULONG ulMethodLength, - _Inout_ LPVOID pMethodData, - ULONG ulDataLength, - _Out_ ULONG* pBytesReturned - ); - - IFACEMETHOD(KsEvent)( - _In_opt_ PKSEVENT pEvent, - ULONG ulEventLength, - _Inout_opt_ LPVOID pEventData, - ULONG ulDataLength, - _Out_opt_ ULONG* pBytesReturned - ); + IFACEMETHOD(KsProperty)(_In_reads_bytes_(ulPropertyLength) PKSPROPERTY pProperty, + _In_ ULONG ulPropertyLength, + _Inout_updates_to_(ulDataLength, *pBytesReturned) LPVOID pPropertyData, + _In_ ULONG ulDataLength, + _Out_ ULONG* pBytesReturned); + IFACEMETHOD(KsMethod)(_In_reads_bytes_(ulMethodLength) PKSMETHOD pMethod, + _In_ ULONG ulMethodLength, + _Inout_updates_to_(ulDataLength, *pBytesReturned) LPVOID pMethodData, + _In_ ULONG ulDataLength, + _Out_ ULONG* pBytesReturned); + IFACEMETHOD(KsEvent)(_In_reads_bytes_opt_(ulEventLength) PKSEVENT pEvent, + _In_ ULONG ulEventLength, + _Inout_updates_to_(ulDataLength, *pBytesReturned) LPVOID pEventData, + _In_ ULONG ulDataLength, + _Out_opt_ ULONG* pBytesReturned); public: HRESULT RuntimeClassInitialize(); private: HRESULT _CheckShutdownRequiresLock(); - HRESULT _ValidatePresentationDescriptor(IMFPresentationDescriptor *pPresentationDescriptor); + HRESULT _ValidatePresentationDescriptor(_In_ IMFPresentationDescriptor *pPresentationDescriptor); CriticalSection _critSec; SourceState _sourceState{ SourceState::Invalid }; diff --git a/general/SimpleMediaSource/MediaSource/SimpleMediaStream.cpp b/general/SimpleMediaSource/MediaSource/SimpleMediaStream.cpp index 2f8b603b..7685b12e 100644 --- a/general/SimpleMediaSource/MediaSource/SimpleMediaStream.cpp +++ b/general/SimpleMediaSource/MediaSource/SimpleMediaStream.cpp @@ -1,4 +1,4 @@ -#include "SimpleMediaStream.h" +#include "stdafx.h" #define NUM_IMAGE_ROWS 240 #define NUM_IMAGE_COLS 320 @@ -6,22 +6,23 @@ #define IMAGE_BUFFER_SIZE_BYTES (NUM_IMAGE_ROWS * NUM_IMAGE_COLS * BYTES_PER_PIXEL) #define IMAGE_ROW_SIZE_BYTES (NUM_IMAGE_COLS * BYTES_PER_PIXEL) -#define CHECKHR_GOTO( val, label ) \ -hr = (val); \ -if( FAILED( hr ) ) { \ - goto label; \ -} - -HRESULT SimpleMediaStream::RuntimeClassInitialize(_In_ SimpleMediaSource *pSource) +HRESULT +SimpleMediaStream::RuntimeClassInitialize( + _In_ SimpleMediaSource *pSource + ) { HRESULT hr = S_OK; ComPtr spTypeHandler; ComPtr attrs; - AsWeak(pSource, &_wpSource); + if (nullptr == pSource) + { + return E_INVALIDARG; + } + RETURN_IF_FAILED (pSource->QueryInterface(IID_PPV_ARGS(&_parent))); // Initialize media type and set the video output media type. - CHECKHR_GOTO(MFCreateMediaType(&_spMediaType), done); + RETURN_IF_FAILED (MFCreateMediaType(&_spMediaType)); _spMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); _spMediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32); _spMediaType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive); @@ -30,52 +31,56 @@ HRESULT SimpleMediaStream::RuntimeClassInitialize(_In_ SimpleMediaSource *pSourc MFSetAttributeRatio(_spMediaType.Get(), MF_MT_FRAME_RATE, 30, 1); MFSetAttributeRatio(_spMediaType.Get(), MF_MT_PIXEL_ASPECT_RATIO, 1, 1); - CHECKHR_GOTO(MFCreateAttributes(&_spAttributes, 10), done); - CHECKHR_GOTO(this->_SetStreamAttributes(_spAttributes.Get()), done); - CHECKHR_GOTO(MFCreateEventQueue(&_spEventQueue), done); + RETURN_IF_FAILED (MFCreateAttributes(&_spAttributes, 10)); + RETURN_IF_FAILED (this->_SetStreamAttributes(_spAttributes.Get())); + RETURN_IF_FAILED (MFCreateEventQueue(&_spEventQueue)); // Initialize stream descriptors - CHECKHR_GOTO(MFCreateStreamDescriptor(0, 1, _spMediaType.GetAddressOf(), &_spStreamDesc), done); + RETURN_IF_FAILED (MFCreateStreamDescriptor(0, 1, _spMediaType.GetAddressOf(), &_spStreamDesc)); - CHECKHR_GOTO(_spStreamDesc->GetMediaTypeHandler(&spTypeHandler), done); - CHECKHR_GOTO(spTypeHandler->SetCurrentMediaType(_spMediaType.Get()), done); - CHECKHR_GOTO(this->_SetStreamDescriptorAttributes(_spStreamDesc.Get()), done); + RETURN_IF_FAILED (_spStreamDesc->GetMediaTypeHandler(&spTypeHandler)); + RETURN_IF_FAILED (spTypeHandler->SetCurrentMediaType(_spMediaType.Get())); + RETURN_IF_FAILED (this->_SetStreamDescriptorAttributes(_spStreamDesc.Get())); -done: return hr; } -//////////////////////////////////////////////////////////////////////////////////////////////////// // IMFMediaEventGenerator -IFACEMETHODIMP SimpleMediaStream::BeginGetEvent(IMFAsyncCallback *pCallback, IUnknown *punkState) +IFACEMETHODIMP +SimpleMediaStream::BeginGetEvent( + _In_ IMFAsyncCallback *pCallback, + _In_ IUnknown *punkState + ) { + HRESULT hr = S_OK; auto lock = _critSec.Lock(); - HRESULT hr = _CheckShutdownRequiresLock(); - - if (SUCCEEDED(hr)) - { - hr = _spEventQueue->BeginGetEvent(pCallback, punkState); - } + RETURN_IF_FAILED (_CheckShutdownRequiresLock()); + RETURN_IF_FAILED (_spEventQueue->BeginGetEvent(pCallback, punkState)); return hr; } -IFACEMETHODIMP SimpleMediaStream::EndGetEvent(IMFAsyncResult *pResult, IMFMediaEvent **ppEvent) +IFACEMETHODIMP +SimpleMediaStream::EndGetEvent( + _In_ IMFAsyncResult *pResult, + _COM_Outptr_ IMFMediaEvent **ppEvent + ) { + HRESULT hr = S_OK; auto lock = _critSec.Lock(); - HRESULT hr = _CheckShutdownRequiresLock(); - - if (SUCCEEDED(hr)) - { - hr = _spEventQueue->EndGetEvent(pResult, ppEvent); - } + RETURN_IF_FAILED (_CheckShutdownRequiresLock()); + RETURN_IF_FAILED (_spEventQueue->EndGetEvent(pResult, ppEvent)); return hr; } -IFACEMETHODIMP SimpleMediaStream::GetEvent(DWORD dwFlags, IMFMediaEvent **ppEvent) +IFACEMETHODIMP +SimpleMediaStream::GetEvent( + DWORD dwFlags, + _COM_Outptr_ IMFMediaEvent **ppEvent + ) { // NOTE: // GetEvent can block indefinitely, so we don't hold the lock. @@ -88,90 +93,80 @@ IFACEMETHODIMP SimpleMediaStream::GetEvent(DWORD dwFlags, IMFMediaEvent **ppEven { auto lock = _critSec.Lock(); - // Check shutdown - hr = _CheckShutdownRequiresLock(); - - if (SUCCEEDED(hr)) - { - spQueue = _spEventQueue; - } + RETURN_IF_FAILED (_CheckShutdownRequiresLock()); + spQueue = _spEventQueue; } // Now get the event. - if (SUCCEEDED(hr)) - { - hr = spQueue->GetEvent(dwFlags, ppEvent); - } + RETURN_IF_FAILED (_spEventQueue->GetEvent(dwFlags, ppEvent)); return hr; } -IFACEMETHODIMP SimpleMediaStream::QueueEvent(MediaEventType met, REFGUID guidExtendedType, HRESULT hrStatus, const PROPVARIANT *pvValue) +IFACEMETHODIMP +SimpleMediaStream::QueueEvent( + MediaEventType eventType, + REFGUID guidExtendedType, + HRESULT hrStatus, + _In_opt_ PROPVARIANT const *pvValue + ) { + HRESULT hr = S_OK; auto lock = _critSec.Lock(); - HRESULT hr = _CheckShutdownRequiresLock(); - if (SUCCEEDED(hr)) - { - hr = _spEventQueue->QueueEventParamVar(met, guidExtendedType, hrStatus, pvValue); - } + RETURN_IF_FAILED (_CheckShutdownRequiresLock()); + RETURN_IF_FAILED (_spEventQueue->QueueEventParamVar(eventType, guidExtendedType, hrStatus, pvValue)); return hr; } -////////////////////////////////////////////////////////////////////////////////////////// // IMFMediaStream -IFACEMETHODIMP SimpleMediaStream::GetMediaSource(IMFMediaSource **ppMediaSource) +IFACEMETHODIMP +SimpleMediaStream::GetMediaSource( + _COM_Outptr_ IMFMediaSource **ppMediaSource + ) { + HRESULT hr = S_OK; + auto lock = _critSec.Lock(); + if (ppMediaSource == nullptr) { return E_POINTER; } *ppMediaSource = nullptr; - auto lock = _critSec.Lock(); - HRESULT hr = _CheckShutdownRequiresLock(); + RETURN_IF_FAILED (_CheckShutdownRequiresLock()); - if (SUCCEEDED(hr)) - { - ComPtr spSource; - _wpSource.As(&spSource); - if (spSource != nullptr) - { - hr = spSource->QueryInterface(IID_PPV_ARGS(ppMediaSource)); - } - else - { - hr = E_UNEXPECTED; - } - } + *ppMediaSource = _parent.Get(); + (*ppMediaSource)->AddRef(); return hr; } -IFACEMETHODIMP SimpleMediaStream::GetStreamDescriptor(IMFStreamDescriptor **ppStreamDescriptor) +IFACEMETHODIMP +SimpleMediaStream::GetStreamDescriptor( + _COM_Outptr_ IMFStreamDescriptor **ppStreamDescriptor + ) { + HRESULT hr = S_OK; + auto lock = _critSec.Lock(); + if (ppStreamDescriptor == nullptr) { return E_POINTER; } - *ppStreamDescriptor = nullptr; - auto lock = _critSec.Lock(); - HRESULT hr = _CheckShutdownRequiresLock(); + RETURN_IF_FAILED (_CheckShutdownRequiresLock()); - if (SUCCEEDED(hr)) + if (_spStreamDesc != nullptr) { - if (_spStreamDesc != nullptr) - { - *ppStreamDescriptor = _spStreamDesc.Get(); - (*ppStreamDescriptor)->AddRef(); - } - else - { - return E_UNEXPECTED; - } + *ppStreamDescriptor = _spStreamDesc.Get(); + (*ppStreamDescriptor)->AddRef(); + } + else + { + return E_UNEXPECTED; } return hr; @@ -188,11 +183,16 @@ IFACEMETHODIMP SimpleMediaStream::GetStreamDescriptor(IMFStreamDescriptor **ppSt pitch - line length in bytes len - length of buffer in bytes */ -HRESULT WriteSampleData(BYTE *pBuf, LONG pitch, DWORD len) +HRESULT +WriteSampleData( + _Inout_updates_bytes_(len) BYTE *pBuf, + _In_ LONG pitch, + _In_ DWORD len + ) { if (pBuf == nullptr) { - return E_POINTER; + return E_INVALIDARG; } const int NUM_ROWS = len / abs(pitch); @@ -209,101 +209,63 @@ HRESULT WriteSampleData(BYTE *pBuf, LONG pitch, DWORD len) return S_OK; } -IFACEMETHODIMP SimpleMediaStream::RequestSample(IUnknown *pToken) +IFACEMETHODIMP +SimpleMediaStream::RequestSample( + _In_ IUnknown *pToken + ) { + HRESULT hr = S_OK; auto lock = _critSec.Lock(); - - HRESULT hr = _CheckShutdownRequiresLock(); - - if (SUCCEEDED(hr)) + ComPtr sample; + ComPtr outputBuffer; + LONG pitch = IMAGE_ROW_SIZE_BYTES; + BYTE *bufferStart = nullptr; // not used + DWORD bufferLength = 0; + BYTE *pbuf = nullptr; + ComPtr buffer2D; + + RETURN_IF_FAILED (_CheckShutdownRequiresLock()); + RETURN_IF_FAILED (MFCreateSample(&sample)); + RETURN_IF_FAILED (MFCreate2DMediaBuffer(NUM_IMAGE_COLS, + NUM_IMAGE_ROWS, + D3DFMT_X8R8G8B8, + false, + &outputBuffer)); + RETURN_IF_FAILED (outputBuffer.As(&buffer2D)); + RETURN_IF_FAILED (buffer2D->Lock2DSize(MF2DBuffer_LockFlags_Write, + &pbuf, + &pitch, + &bufferStart, + &bufferLength)); + RETURN_IF_FAILED (WriteSampleData(pbuf, pitch, bufferLength)); + RETURN_IF_FAILED (buffer2D->Unlock2D()); + RETURN_IF_FAILED (sample->AddBuffer(outputBuffer.Get())); + RETURN_IF_FAILED (sample->SetSampleTime(MFGetSystemTime())); + RETURN_IF_FAILED (sample->SetSampleDuration(333333)); + if (pToken != nullptr) { - ComPtr spSample; - - ComPtr spOutputBuffer; - hr = MFCreate2DMediaBuffer(NUM_IMAGE_COLS, NUM_IMAGE_ROWS, D3DFMT_X8R8G8B8, false, &spOutputBuffer); - - LONG pitch = IMAGE_ROW_SIZE_BYTES; - BYTE *bufferStart = nullptr; // not used, since in this example we know the image will be top down, so bufferStart == pBuf - DWORD bufferLength = IMAGE_BUFFER_SIZE_BYTES; - - BYTE *pBuf = nullptr; - ComPtr spBuffer2D; - if (SUCCEEDED(hr)) - { - hr = spOutputBuffer.As(&spBuffer2D); - } - - if (SUCCEEDED(hr)) - { - if (spBuffer2D != nullptr) - { - hr = spBuffer2D->Lock2DSize(MF2DBuffer_LockFlags_Write, &pBuf, &pitch, &bufferStart, &bufferLength); - } - else - { - hr = spOutputBuffer->Lock(&pBuf, nullptr, nullptr); - } - } - - if (SUCCEEDED(hr)) - { - hr = WriteSampleData(pBuf, pitch, bufferLength); - } - - if (SUCCEEDED(hr)) - { - hr = spOutputBuffer->SetCurrentLength(bufferLength); - } - - if (SUCCEEDED(hr)) - { - hr = spBuffer2D->Unlock2D(); - } - - if (SUCCEEDED(hr)) - { - hr = MFCreateSample(&spSample); - } - - if (SUCCEEDED(hr)) - { - hr = spSample->AddBuffer(spOutputBuffer.Get()); - } - - // set timestamp - if (SUCCEEDED(hr)) - { - hr = spSample->SetSampleTime(MFGetSystemTime()); - } - if (SUCCEEDED(hr)) - { - hr = spSample->SetSampleDuration(330000); - } - - if (pToken != nullptr) - { - hr = spSample->SetUnknown(MFSampleExtension_Token, pToken); - } - - if (SUCCEEDED(hr)) - { - hr = _spEventQueue->QueueEventParamUnk(MEMediaSample, GUID_NULL, S_OK, spSample.Get()); - } + RETURN_IF_FAILED (sample->SetUnknown(MFSampleExtension_Token, pToken)); } + RETURN_IF_FAILED (_spEventQueue->QueueEventParamUnk(MEMediaSample, + GUID_NULL, + S_OK, + sample.Get())); return hr; } ////////////////////////////////////////////////////////////////////////////////////////// // IMFMediaStream2 -IFACEMETHODIMP SimpleMediaStream::SetStreamState(MF_STREAM_STATE state) +IFACEMETHODIMP +SimpleMediaStream::SetStreamState( + MF_STREAM_STATE state + ) { - bool runningState = false; - auto lock = _critSec.Lock(); - HRESULT hr = S_OK; + auto lock = _critSec.Lock(); + bool runningState = false; - CHECKHR_GOTO(_CheckShutdownRequiresLock(), done); + RETURN_IF_FAILED (_CheckShutdownRequiresLock()); switch (state) { @@ -326,12 +288,16 @@ done: return hr; } -IFACEMETHODIMP SimpleMediaStream::GetStreamState(_Out_ MF_STREAM_STATE *pState) +IFACEMETHODIMP +SimpleMediaStream::GetStreamState( + _Out_ MF_STREAM_STATE *pState + ) { + HRESULT hr = S_OK; auto lock = _critSec.Lock(); BOOLEAN pauseState = false; - HRESULT hr = _CheckShutdownRequiresLock(); + RETURN_IF_FAILED (_CheckShutdownRequiresLock()); if (SUCCEEDED(hr)) { @@ -341,12 +307,15 @@ IFACEMETHODIMP SimpleMediaStream::GetStreamState(_Out_ MF_STREAM_STATE *pState) return hr; } -HRESULT SimpleMediaStream::Shutdown() +HRESULT +SimpleMediaStream::Shutdown( + ) { HRESULT hr = S_OK; auto lock = _critSec.Lock(); _isShutdown = true; + _parent.Reset(); if (_spEventQueue != nullptr) { @@ -360,12 +329,12 @@ HRESULT SimpleMediaStream::Shutdown() _isSelected = false; - _wpSource.Reset(); - return hr; } -HRESULT SimpleMediaStream::_CheckShutdownRequiresLock() +HRESULT +SimpleMediaStream::_CheckShutdownRequiresLock( + ) { if (_isShutdown) { @@ -380,28 +349,43 @@ HRESULT SimpleMediaStream::_CheckShutdownRequiresLock() return S_OK; } -HRESULT SimpleMediaStream::_SetStreamAttributes(IMFAttributes *pAttributeStore) +HRESULT +SimpleMediaStream::_SetStreamAttributes( + _In_ IMFAttributes *pAttributeStore + ) { HRESULT hr = S_OK; - if (SUCCEEDED(hr)) { hr = pAttributeStore->SetGUID(MF_DEVICESTREAM_STREAM_CATEGORY, PINNAME_VIDEO_CAPTURE); } - if (SUCCEEDED(hr)) { hr = pAttributeStore->SetUINT32(MF_DEVICESTREAM_STREAM_ID, STREAMINDEX); } - if (SUCCEEDED(hr)) { hr = pAttributeStore->SetUINT32(MF_DEVICESTREAM_FRAMESERVER_SHARED, 1); } + if (nullptr == pAttributeStore) + { + return E_INVALIDARG; + } - if (SUCCEEDED(hr)) { hr = pAttributeStore->SetUINT32(MF_DEVICESTREAM_ATTRIBUTE_FRAMESOURCE_TYPES, _MFFrameSourceTypes::MFFrameSourceTypes_Color); } + RETURN_IF_FAILED (pAttributeStore->SetGUID(MF_DEVICESTREAM_STREAM_CATEGORY, PINNAME_VIDEO_CAPTURE)); + RETURN_IF_FAILED (pAttributeStore->SetUINT32(MF_DEVICESTREAM_STREAM_ID, STREAMINDEX)); + RETURN_IF_FAILED (pAttributeStore->SetUINT32(MF_DEVICESTREAM_FRAMESERVER_SHARED, 1)); + RETURN_IF_FAILED (pAttributeStore->SetUINT32(MF_DEVICESTREAM_ATTRIBUTE_FRAMESOURCE_TYPES, _MFFrameSourceTypes::MFFrameSourceTypes_Color)); return hr; } -HRESULT SimpleMediaStream::_SetStreamDescriptorAttributes(IMFAttributes *pAttributeStore) +HRESULT +SimpleMediaStream::_SetStreamDescriptorAttributes( + _In_ IMFAttributes *pAttributeStore + ) { HRESULT hr = S_OK; - if (SUCCEEDED(hr)) { hr = pAttributeStore->SetGUID(MF_DEVICESTREAM_STREAM_CATEGORY, PINNAME_VIDEO_CAPTURE); } - if (SUCCEEDED(hr)) { hr = pAttributeStore->SetUINT32(MF_DEVICESTREAM_STREAM_ID, STREAMINDEX); } - if (SUCCEEDED(hr)) { hr = pAttributeStore->SetUINT32(MF_DEVICESTREAM_FRAMESERVER_SHARED, 1); } + if (nullptr == pAttributeStore) + { + return E_INVALIDARG; + } - if (SUCCEEDED(hr)) { hr = pAttributeStore->SetUINT32(MF_DEVICESTREAM_ATTRIBUTE_FRAMESOURCE_TYPES, _MFFrameSourceTypes::MFFrameSourceTypes_Color); } + RETURN_IF_FAILED (pAttributeStore->SetGUID(MF_DEVICESTREAM_STREAM_CATEGORY, PINNAME_VIDEO_CAPTURE)); + RETURN_IF_FAILED (pAttributeStore->SetUINT32(MF_DEVICESTREAM_STREAM_ID, STREAMINDEX)); + RETURN_IF_FAILED (pAttributeStore->SetUINT32(MF_DEVICESTREAM_FRAMESERVER_SHARED, 1)); + RETURN_IF_FAILED (pAttributeStore->SetUINT32(MF_DEVICESTREAM_ATTRIBUTE_FRAMESOURCE_TYPES, _MFFrameSourceTypes::MFFrameSourceTypes_Color)); return hr; -} \ No newline at end of file +} + diff --git a/general/SimpleMediaSource/MediaSource/SimpleMediaStream.h b/general/SimpleMediaSource/MediaSource/SimpleMediaStream.h index b804b1ea..56351f47 100644 --- a/general/SimpleMediaSource/MediaSource/SimpleMediaStream.h +++ b/general/SimpleMediaSource/MediaSource/SimpleMediaStream.h @@ -1,7 +1,6 @@ #pragma once #include "stdafx.h" -#include "SimpleMediaSource.h" class SimpleMediaSource; @@ -29,19 +28,20 @@ public: IFACEMETHOD(SetStreamState)(MF_STREAM_STATE state); IFACEMETHOD(GetStreamState)(_Out_ MF_STREAM_STATE *pState); -public: + // Non-interface methods. HRESULT RuntimeClassInitialize(_In_ SimpleMediaSource* pSource); HRESULT Shutdown(); -private: - HRESULT _CheckShutdownRequiresLock(); + +protected: + HRESULT _CheckShutdownRequiresLock(); HRESULT _SetStreamAttributes(IMFAttributes* pAttributeStore); HRESULT _SetStreamDescriptorAttributes(IMFAttributes* pAttributeStore); -private: - CriticalSection _critSec; - WeakRef _wpSource; + CriticalSection _critSec; + + ComPtr _parent; ComPtr _spEventQueue; ComPtr _spAttributes; ComPtr _spMediaType; diff --git a/general/SimpleMediaSource/MediaSource/stdafx.h b/general/SimpleMediaSource/MediaSource/stdafx.h index 4702e47e..73bec0b4 100644 --- a/general/SimpleMediaSource/MediaSource/stdafx.h +++ b/general/SimpleMediaSource/MediaSource/stdafx.h @@ -7,12 +7,12 @@ // Windows Header Files: #include -#include -#include #include //#include // Must be included before , or else DirectDraw GUIDs will be defined twice. See the comment in . #include #include +#include +#include #include #include #include @@ -21,7 +21,56 @@ #include #include #include -#include using namespace Microsoft::WRL; -using namespace Microsoft::WRL::Wrappers; \ No newline at end of file +using namespace Microsoft::WRL::Wrappers; + +#if !defined(_IKsControl_) +#define _IKsControl_ +interface DECLSPEC_UUID("28F54685-06FD-11D2-B27A-00A0C9223196") IKsControl; +#undef INTERFACE +#define INTERFACE IKsControl +DECLARE_INTERFACE_(IKsControl, IUnknown) +{ + STDMETHOD(KsProperty)( + THIS_ + IN PKSPROPERTY Property, + IN ULONG PropertyLength, + IN OUT LPVOID PropertyData, + IN ULONG DataLength, + OUT ULONG* BytesReturned + ) PURE; + STDMETHOD(KsMethod)( + THIS_ + IN PKSMETHOD Method, + IN ULONG MethodLength, + IN OUT LPVOID MethodData, + IN ULONG DataLength, + OUT ULONG* BytesReturned + ) PURE; + STDMETHOD(KsEvent)( + THIS_ + IN PKSEVENT Event OPTIONAL, + IN ULONG EventLength, + IN OUT LPVOID EventData, + IN ULONG DataLength, + OUT ULONG* BytesReturned + ) PURE; +}; +#endif // _IKsControl_ + +#include "SimpleMediaStream.h" +#include "SimpleMediaSource.h" + + +// Basic macros to handle HRESULT checks. +// Recommend adding implementation specific logging within the failure case. +#ifndef RETURN_IF_FAILED +#define RETURN_IF_FAILED( val ) \ + hr = (val); \ + if ( FAILED( hr ) ) \ + { \ + return hr; \ + } +#endif + -- cgit v1.3.1 From fd1d9958e8df60ad1e3dfb4312d4ff13e1e7ea92 Mon Sep 17 00:00:00 2001 From: Peihsun Yeh Date: Tue, 14 Aug 2018 10:48:12 -0700 Subject: Renamed MediaSource project --- general/SimpleMediaSource/MediaSource/MediaSource.vcxproj | 1 + 1 file changed, 1 insertion(+) (limited to 'general/SimpleMediaSource') diff --git a/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj b/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj index da95eecd..ea726a92 100644 --- a/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj +++ b/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj @@ -23,6 +23,7 @@ {43AD9BF7-E765-48FE-9826-71A8F2CB12DD} MediaSource 10.0.17134.0 + SimpleMediaSource -- cgit v1.3.1 From c6a43d3aad9a76d1ba702e4cabd394082ce4f70a Mon Sep 17 00:00:00 2001 From: Peihsun Yeh Date: Tue, 14 Aug 2018 12:16:17 -0700 Subject: Added driver project, but it is not building yet --- general/SimpleMediaSource/SimpleMediaSource.sln | 34 +++ .../SimpleMediaSourceDriver/Device.c | 115 ++++++++++ .../SimpleMediaSourceDriver/Device.h | 46 ++++ .../SimpleMediaSourceDriver/Driver.c | 167 +++++++++++++++ .../SimpleMediaSourceDriver/Driver.h | 37 ++++ .../SimpleMediaSourceDriver/Public.h | 24 +++ .../SimpleMediaSourceDriver/Queue.c | 193 +++++++++++++++++ .../SimpleMediaSourceDriver/Queue.h | 42 ++++ .../SimpleMediaSourceDriver/ReadMe.txt | 33 +++ .../SimpleMediaSourceDriver.inf | Bin 0 -> 8500 bytes .../SimpleMediaSourceDriver.vcxproj | 238 +++++++++++++++++++++ .../SimpleMediaSourceDriver.vcxproj.filters | 57 +++++ .../SimpleMediaSourceDriver/Trace.h | 62 ++++++ 13 files changed, 1048 insertions(+) create mode 100644 general/SimpleMediaSource/SimpleMediaSourceDriver/Device.c create mode 100644 general/SimpleMediaSource/SimpleMediaSourceDriver/Device.h create mode 100644 general/SimpleMediaSource/SimpleMediaSourceDriver/Driver.c create mode 100644 general/SimpleMediaSource/SimpleMediaSourceDriver/Driver.h create mode 100644 general/SimpleMediaSource/SimpleMediaSourceDriver/Public.h create mode 100644 general/SimpleMediaSource/SimpleMediaSourceDriver/Queue.c create mode 100644 general/SimpleMediaSource/SimpleMediaSourceDriver/Queue.h create mode 100644 general/SimpleMediaSource/SimpleMediaSourceDriver/ReadMe.txt create mode 100644 general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.inf create mode 100644 general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.vcxproj create mode 100644 general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.vcxproj.filters create mode 100644 general/SimpleMediaSource/SimpleMediaSourceDriver/Trace.h (limited to 'general/SimpleMediaSource') diff --git a/general/SimpleMediaSource/SimpleMediaSource.sln b/general/SimpleMediaSource/SimpleMediaSource.sln index dd03ec69..c7b0e366 100644 --- a/general/SimpleMediaSource/SimpleMediaSource.sln +++ b/general/SimpleMediaSource/SimpleMediaSource.sln @@ -5,22 +5,56 @@ VisualStudioVersion = 15.0.27703.2026 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MediaSource", "MediaSource\MediaSource.vcxproj", "{43AD9BF7-E765-48FE-9826-71A8F2CB12DD}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleMediaSourceDriver", "SimpleMediaSourceDriver\SimpleMediaSourceDriver.vcxproj", "{3098C6BF-E96E-4793-A70E-FB09B741580A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|ARM64 = Debug|ARM64 Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 + Release|ARM = Release|ARM + Release|ARM64 = Release|ARM64 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Debug|ARM.ActiveCfg = Debug|Win32 + {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Debug|ARM64.ActiveCfg = Debug|Win32 {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Debug|x64.ActiveCfg = Debug|x64 {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Debug|x64.Build.0 = Debug|x64 {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Debug|x86.ActiveCfg = Debug|Win32 {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Debug|x86.Build.0 = Debug|Win32 + {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Release|ARM.ActiveCfg = Release|Win32 + {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Release|ARM64.ActiveCfg = Release|Win32 {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Release|x64.ActiveCfg = Release|x64 {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Release|x64.Build.0 = Release|x64 {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Release|x86.ActiveCfg = Release|Win32 {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Release|x86.Build.0 = Release|Win32 + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Debug|ARM.ActiveCfg = Debug|ARM + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Debug|ARM.Build.0 = Debug|ARM + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Debug|ARM.Deploy.0 = Debug|ARM + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Debug|ARM64.Build.0 = Debug|ARM64 + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Debug|x64.ActiveCfg = Debug|x64 + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Debug|x64.Build.0 = Debug|x64 + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Debug|x64.Deploy.0 = Debug|x64 + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Debug|x86.ActiveCfg = Debug|Win32 + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Debug|x86.Build.0 = Debug|Win32 + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Debug|x86.Deploy.0 = Debug|Win32 + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Release|ARM.ActiveCfg = Release|ARM + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Release|ARM.Build.0 = Release|ARM + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Release|ARM.Deploy.0 = Release|ARM + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Release|ARM64.ActiveCfg = Release|ARM64 + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Release|ARM64.Build.0 = Release|ARM64 + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Release|ARM64.Deploy.0 = Release|ARM64 + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Release|x64.ActiveCfg = Release|x64 + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Release|x64.Build.0 = Release|x64 + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Release|x64.Deploy.0 = Release|x64 + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Release|x86.ActiveCfg = Release|Win32 + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Release|x86.Build.0 = Release|Win32 + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Release|x86.Deploy.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/general/SimpleMediaSource/SimpleMediaSourceDriver/Device.c b/general/SimpleMediaSource/SimpleMediaSourceDriver/Device.c new file mode 100644 index 00000000..0cf7979e --- /dev/null +++ b/general/SimpleMediaSource/SimpleMediaSourceDriver/Device.c @@ -0,0 +1,115 @@ +/*++ + +Module Name: + + device.c - Device handling events for example driver. + +Abstract: + + This file contains the device entry points and callbacks. + +Environment: + + User-mode Driver Framework 2 + +--*/ + +#include "driver.h" +#include "device.tmh" + +GUID CAMERA_CATEGORY = { STATIC_KSCATEGORY_VIDEO_CAMERA }; +GUID CAPTURE_CATEGORY = { STATIC_KSCATEGORY_CAPTURE }; +GUID VIDEO_CATEGORY = { STATIC_KSCATEGORY_VIDEO }; + +NTSTATUS +SimpleMediaSourceDriverCreateDevice( + _Inout_ PWDFDEVICE_INIT DeviceInit + ) +/*++ + +Routine Description: + + Worker routine called to create a device and its software resources. + +Arguments: + + DeviceInit - Pointer to an opaque init structure. Memory for this + structure will be freed by the framework when the WdfDeviceCreate + succeeds. So don't access the structure after that point. + +Return Value: + + NTSTATUS + +--*/ +{ + WDF_OBJECT_ATTRIBUTES deviceAttributes; + PDEVICE_CONTEXT deviceContext; + WDFDEVICE device; + NTSTATUS status; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT); + + status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device); + + if (NT_SUCCESS(status)) { + // + // Get a pointer to the device context structure that we just associated + // with the device object. We define this structure in the device.h + // header file. DeviceGetContext is an inline function generated by + // using the WDF_DECLARE_CONTEXT_TYPE_WITH_NAME macro in device.h. + // This function will do the type checking and return the device context. + // If you pass a wrong object handle it will return NULL and assert if + // run under framework verifier mode. + // + deviceContext = DeviceGetContext(device); + + // + // Initialize the context. + // + deviceContext->PrivateDeviceData = 0; + + // + // Create a device interface so that applications can find and talk + // to us. + // + status = WdfDeviceCreateDeviceInterface( + device, + &GUID_DEVINTERFACE_SimpleMediaSourceDriver, + NULL // ReferenceString + ); + + if (NT_SUCCESS(status)) { + // + // Create a device interface so that application can find and talk + // to us. + // + status = WdfDeviceCreateDeviceInterface( + device, + &CAPTURE_CATEGORY, + NULL // ReferenceString + ); + } + + if (NT_SUCCESS(status)) { + // + // Create a device interface so that application can find and talk + // to us. + // + status = WdfDeviceCreateDeviceInterface( + device, + &VIDEO_CATEGORY, + NULL // ReferenceString + ); + } + + if (NT_SUCCESS(status)) { + // + // Initialize the I/O Package and any Queues + // + status = SimpleMediaSourceDriverQueueInitialize(device); + } + } + + return status; +} diff --git a/general/SimpleMediaSource/SimpleMediaSourceDriver/Device.h b/general/SimpleMediaSource/SimpleMediaSourceDriver/Device.h new file mode 100644 index 00000000..6c2da5e4 --- /dev/null +++ b/general/SimpleMediaSource/SimpleMediaSourceDriver/Device.h @@ -0,0 +1,46 @@ +/*++ + +Module Name: + + device.h + +Abstract: + + This file contains the device definitions. + +Environment: + + User-mode Driver Framework 2 + +--*/ + +#include "public.h" + +EXTERN_C_START + +// +// The device context performs the same job as +// a WDM device extension in the driver frameworks +// +typedef struct _DEVICE_CONTEXT +{ + ULONG PrivateDeviceData; // just a placeholder + +} DEVICE_CONTEXT, *PDEVICE_CONTEXT; + +// +// This macro will generate an inline function called DeviceGetContext +// which will be used to get a pointer to the device context memory +// in a type safe manner. +// +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_CONTEXT, DeviceGetContext) + +// +// Function to initialize the device and its callbacks +// +NTSTATUS +SimpleMediaSourceDriverCreateDevice( + _Inout_ PWDFDEVICE_INIT DeviceInit + ); + +EXTERN_C_END diff --git a/general/SimpleMediaSource/SimpleMediaSourceDriver/Driver.c b/general/SimpleMediaSource/SimpleMediaSourceDriver/Driver.c new file mode 100644 index 00000000..94ee0fa9 --- /dev/null +++ b/general/SimpleMediaSource/SimpleMediaSourceDriver/Driver.c @@ -0,0 +1,167 @@ +/*++ + +Module Name: + + driver.c + +Abstract: + + This file contains the driver entry points and callbacks. + +Environment: + + User-mode Driver Framework 2 + +--*/ + +#include "driver.h" +#include "driver.tmh" + +NTSTATUS +DriverEntry( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING RegistryPath + ) +/*++ + +Routine Description: + DriverEntry initializes the driver and is the first routine called by the + system after the driver is loaded. DriverEntry specifies the other entry + points in the function driver, such as EvtDevice and DriverUnload. + +Parameters Description: + + DriverObject - represents the instance of the function driver that is loaded + into memory. DriverEntry must initialize members of DriverObject before it + returns to the caller. DriverObject is allocated by the system before the + driver is loaded, and it is released by the system after the system unloads + the function driver from memory. + + RegistryPath - represents the driver specific path in the Registry. + The function driver can use the path to store driver related data between + reboots. The path does not store hardware instance specific data. + +Return Value: + + STATUS_SUCCESS if successful, + STATUS_UNSUCCESSFUL otherwise. + +--*/ +{ + WDF_DRIVER_CONFIG config; + NTSTATUS status; + WDF_OBJECT_ATTRIBUTES attributes; + + // + // Initialize WPP Tracing + // +#if UMDF_VERSION_MAJOR == 2 && UMDF_VERSION_MINOR == 0 + WPP_INIT_TRACING(MYDRIVER_TRACING_ID); +#else + WPP_INIT_TRACING( DriverObject, RegistryPath ); +#endif + + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry"); + + // + // Register a cleanup callback so that we can call WPP_CLEANUP when + // the framework driver object is deleted during driver unload. + // + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.EvtCleanupCallback = SimpleMediaSourceDriverEvtDriverContextCleanup; + + WDF_DRIVER_CONFIG_INIT(&config, + SimpleMediaSourceDriverEvtDeviceAdd + ); + + status = WdfDriverCreate(DriverObject, + RegistryPath, + &attributes, + &config, + WDF_NO_HANDLE + ); + + if (!NT_SUCCESS(status)) { + TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "WdfDriverCreate failed %!STATUS!", status); +#if UMDF_VERSION_MAJOR == 2 && UMDF_VERSION_MINOR == 0 + WPP_CLEANUP(); +#else + WPP_CLEANUP(DriverObject); +#endif + return status; + } + + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit"); + + return status; +} + +NTSTATUS +SimpleMediaSourceDriverEvtDeviceAdd( + _In_ WDFDRIVER Driver, + _Inout_ PWDFDEVICE_INIT DeviceInit + ) +/*++ +Routine Description: + + EvtDeviceAdd is called by the framework in response to AddDevice + call from the PnP manager. We create and initialize a device object to + represent a new instance of the device. + +Arguments: + + Driver - Handle to a framework driver object created in DriverEntry + + DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. + +Return Value: + + NTSTATUS + +--*/ +{ + NTSTATUS status; + + UNREFERENCED_PARAMETER(Driver); + + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry"); + + status = SimpleMediaSourceDriverCreateDevice(DeviceInit); + + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit"); + + return status; +} + +VOID +SimpleMediaSourceDriverEvtDriverContextCleanup( + _In_ WDFOBJECT DriverObject + ) +/*++ +Routine Description: + + Free all the resources allocated in DriverEntry. + +Arguments: + + DriverObject - handle to a WDF Driver object. + +Return Value: + + VOID. + +--*/ +{ + UNREFERENCED_PARAMETER(DriverObject); + + TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry"); + + // + // Stop WPP Tracing + // +#if UMDF_VERSION_MAJOR == 2 && UMDF_VERSION_MINOR == 0 + WPP_CLEANUP(); +#else + WPP_CLEANUP(WdfDriverWdmGetDriverObject((WDFDRIVER)DriverObject)); +#endif +} diff --git a/general/SimpleMediaSource/SimpleMediaSourceDriver/Driver.h b/general/SimpleMediaSource/SimpleMediaSourceDriver/Driver.h new file mode 100644 index 00000000..1e19eec9 --- /dev/null +++ b/general/SimpleMediaSource/SimpleMediaSourceDriver/Driver.h @@ -0,0 +1,37 @@ +/*++ + +Module Name: + + driver.h + +Abstract: + + This file contains the driver definitions. + +Environment: + + User-mode Driver Framework 2 + +--*/ + +#include +#include +#include +#include +#include + +#include "device.h" +#include "queue.h" +#include "trace.h" + +EXTERN_C_START + +// +// WDFDRIVER Events +// + +DRIVER_INITIALIZE DriverEntry; +EVT_WDF_DRIVER_DEVICE_ADD SimpleMediaSourceDriverEvtDeviceAdd; +EVT_WDF_OBJECT_CONTEXT_CLEANUP SimpleMediaSourceDriverEvtDriverContextCleanup; + +EXTERN_C_END diff --git a/general/SimpleMediaSource/SimpleMediaSourceDriver/Public.h b/general/SimpleMediaSource/SimpleMediaSourceDriver/Public.h new file mode 100644 index 00000000..f3d4964b --- /dev/null +++ b/general/SimpleMediaSource/SimpleMediaSourceDriver/Public.h @@ -0,0 +1,24 @@ +/*++ + +Module Name: + + public.h + +Abstract: + + This module contains the common declarations shared by driver + and user applications. + +Environment: + + driver and application + +--*/ + +// +// Define an Interface Guid so that apps can find the device and talk to it. +// + +DEFINE_GUID (GUID_DEVINTERFACE_SimpleMediaSourceDriver, + 0xb5036295,0xf041,0x4506,0x88,0xdc,0xcb,0x16,0x5c,0x4d,0x67,0x8c); +// {b5036295-f041-4506-88dc-cb165c4d678c} diff --git a/general/SimpleMediaSource/SimpleMediaSourceDriver/Queue.c b/general/SimpleMediaSource/SimpleMediaSourceDriver/Queue.c new file mode 100644 index 00000000..6ea51781 --- /dev/null +++ b/general/SimpleMediaSource/SimpleMediaSourceDriver/Queue.c @@ -0,0 +1,193 @@ +/*++ + +Module Name: + + queue.c + +Abstract: + + This file contains the queue entry points and callbacks. + +Environment: + + User-mode Driver Framework 2 + +--*/ + +#include "driver.h" +#include "queue.tmh" + +NTSTATUS +SimpleMediaSourceDriverQueueInitialize( + _In_ WDFDEVICE Device + ) +/*++ + +Routine Description: + + The I/O dispatch callbacks for the frameworks device object + are configured in this function. + + A single default I/O Queue is configured for parallel request + processing, and a driver context memory allocation is created + to hold our structure QUEUE_CONTEXT. + +Arguments: + + Device - Handle to a framework device object. + +Return Value: + + VOID + +--*/ +{ + WDFQUEUE queue; + NTSTATUS status; + WDF_IO_QUEUE_CONFIG queueConfig; + + // + // Configure a default queue so that requests that are not + // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto + // other queues get dispatched here. + // + WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE( + &queueConfig, + WdfIoQueueDispatchParallel + ); + + queueConfig.EvtIoDeviceControl = SimpleMediaSourceDriverEvtIoDeviceControl; + queueConfig.EvtIoStop = SimpleMediaSourceDriverEvtIoStop; + + status = WdfIoQueueCreate( + Device, + &queueConfig, + WDF_NO_OBJECT_ATTRIBUTES, + &queue + ); + + if(!NT_SUCCESS(status)) { + TraceEvents(TRACE_LEVEL_ERROR, TRACE_QUEUE, "WdfIoQueueCreate failed %!STATUS!", status); + return status; + } + + return status; +} + +VOID +SimpleMediaSourceDriverEvtIoDeviceControl( + _In_ WDFQUEUE Queue, + _In_ WDFREQUEST Request, + _In_ size_t OutputBufferLength, + _In_ size_t InputBufferLength, + _In_ ULONG IoControlCode + ) +/*++ + +Routine Description: + + This event is invoked when the framework receives IRP_MJ_DEVICE_CONTROL request. + +Arguments: + + Queue - Handle to the framework queue object that is associated with the + I/O request. + + Request - Handle to a framework request object. + + OutputBufferLength - Size of the output buffer in bytes + + InputBufferLength - Size of the input buffer in bytes + + IoControlCode - I/O control code. + +Return Value: + + VOID + +--*/ +{ + TraceEvents(TRACE_LEVEL_INFORMATION, + TRACE_QUEUE, + "%!FUNC! Queue 0x%p, Request 0x%p OutputBufferLength %d InputBufferLength %d IoControlCode %d", + Queue, Request, (int) OutputBufferLength, (int) InputBufferLength, IoControlCode); + + WdfRequestComplete(Request, STATUS_SUCCESS); + + return; +} + +VOID +SimpleMediaSourceDriverEvtIoStop( + _In_ WDFQUEUE Queue, + _In_ WDFREQUEST Request, + _In_ ULONG ActionFlags +) +/*++ + +Routine Description: + + This event is invoked for a power-managed queue before the device leaves the working state (D0). + +Arguments: + + Queue - Handle to the framework queue object that is associated with the + I/O request. + + Request - Handle to a framework request object. + + ActionFlags - A bitwise OR of one or more WDF_REQUEST_STOP_ACTION_FLAGS-typed flags + that identify the reason that the callback function is being called + and whether the request is cancelable. + +Return Value: + + VOID + +--*/ +{ + TraceEvents(TRACE_LEVEL_INFORMATION, + TRACE_QUEUE, + "%!FUNC! Queue 0x%p, Request 0x%p ActionFlags %d", + Queue, Request, ActionFlags); + + // + // In most cases, the EvtIoStop callback function completes, cancels, or postpones + // further processing of the I/O request. + // + // Typically, the driver uses the following rules: + // + // - If the driver owns the I/O request, it calls WdfRequestUnmarkCancelable + // (if the request is cancelable) and either calls WdfRequestStopAcknowledge + // with a Requeue value of TRUE, or it calls WdfRequestComplete with a + // completion status value of STATUS_SUCCESS or STATUS_CANCELLED. + // + // Before it can call these methods safely, the driver must make sure that + // its implementation of EvtIoStop has exclusive access to the request. + // + // In order to do that, the driver must synchronize access to the request + // to prevent other threads from manipulating the request concurrently. + // The synchronization method you choose will depend on your driver's design. + // + // For example, if the request is held in a shared context, the EvtIoStop callback + // might acquire an internal driver lock, take the request from the shared context, + // and then release the lock. At this point, the EvtIoStop callback owns the request + // and can safely complete or requeue the request. + // + // - If the driver has forwarded the I/O request to an I/O target, it either calls + // WdfRequestCancelSentRequest to attempt to cancel the request, or it postpones + // further processing of the request and calls WdfRequestStopAcknowledge with + // a Requeue value of FALSE. + // + // A driver might choose to take no action in EvtIoStop for requests that are + // guaranteed to complete in a small amount of time. + // + // In this case, the framework waits until the specified request is complete + // before moving the device (or system) to a lower power state or removing the device. + // Potentially, this inaction can prevent a system from entering its hibernation state + // or another low system power state. In extreme cases, it can cause the system + // to crash with bugcheck code 9F. + // + + return; +} diff --git a/general/SimpleMediaSource/SimpleMediaSourceDriver/Queue.h b/general/SimpleMediaSource/SimpleMediaSourceDriver/Queue.h new file mode 100644 index 00000000..e0c01283 --- /dev/null +++ b/general/SimpleMediaSource/SimpleMediaSourceDriver/Queue.h @@ -0,0 +1,42 @@ +/*++ + +Module Name: + + queue.h + +Abstract: + + This file contains the queue definitions. + +Environment: + + User-mode Driver Framework 2 + +--*/ + +EXTERN_C_START + +// +// This is the context that can be placed per queue +// and would contain per queue information. +// +typedef struct _QUEUE_CONTEXT { + + ULONG PrivateDeviceData; // just a placeholder + +} QUEUE_CONTEXT, *PQUEUE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(QUEUE_CONTEXT, QueueGetContext) + +NTSTATUS +SimpleMediaSourceDriverQueueInitialize( + _In_ WDFDEVICE Device + ); + +// +// Events from the IoQueue object +// +EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL SimpleMediaSourceDriverEvtIoDeviceControl; +EVT_WDF_IO_QUEUE_IO_STOP SimpleMediaSourceDriverEvtIoStop; + +EXTERN_C_END diff --git a/general/SimpleMediaSource/SimpleMediaSourceDriver/ReadMe.txt b/general/SimpleMediaSource/SimpleMediaSourceDriver/ReadMe.txt new file mode 100644 index 00000000..55d9dadd --- /dev/null +++ b/general/SimpleMediaSource/SimpleMediaSourceDriver/ReadMe.txt @@ -0,0 +1,33 @@ +======================================================================== + SimpleMediaSourceDriver Project Overview +======================================================================== + +This file contains a summary of what you will find in each of the files that make up your project. + +SimpleMediaSourceDriver.vcxproj + This is the main project file for projects generated using an Application Wizard. + It contains information about the version of the product that generated the file, and + information about the platforms, configurations, and project features selected with the + Application Wizard. + +SimpleMediaSourceDriver.vcxproj.filters + This is the filters file for VC++ projects generated using an Application Wizard. + It contains information about the association between the files in your project + and the filters. This association is used in the IDE to show grouping of files with + similar extensions under a specific node (for e.g. ".cpp" files are associated with the + "Source Files" filter). + +Public.h + Header file to be shared with applications. + +Driver.c & Driver.h + DriverEntry and WDFDRIVER related functionality and callbacks. + +Device.c & Device.h + WDFDEVICE related functionality and callbacks. + +Queue.c & Queue.h + WDFQUEUE related functionality and callbacks. + +Trace.h + Definitions for WPP tracing. diff --git a/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.inf b/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.inf new file mode 100644 index 00000000..dabb3237 Binary files /dev/null and b/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.inf differ diff --git a/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.vcxproj b/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.vcxproj new file mode 100644 index 00000000..c3afadf5 --- /dev/null +++ b/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.vcxproj @@ -0,0 +1,238 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + Debug + ARM + + + Release + ARM + + + Debug + ARM64 + + + Release + ARM64 + + + + + + + + + + + + + + + + + + + + + + {3098C6BF-E96E-4793-A70E-FB09B741580A} + {32909489-7be5-497b-aafa-db6669d9b44b} + v4.5 + 12.0 + Debug + Win32 + SimpleMediaSourceDriver + + + WindowsUserModeDriver10.0 + DynamicLibrary + Universal + + + WindowsUserModeDriver10.0 + DynamicLibrary + Universal + + + WindowsUserModeDriver10.0 + DynamicLibrary + Universal + + + WindowsUserModeDriver10.0 + DynamicLibrary + Universal + + + WindowsUserModeDriver10.0 + DynamicLibrary + Universal + + + WindowsUserModeDriver10.0 + DynamicLibrary + Universal + + + WindowsUserModeDriver10.0 + DynamicLibrary + Universal + + + WindowsUserModeDriver10.0 + DynamicLibrary + Universal + + + + Windows10 + true + 2 + + + Windows10 + false + 2 + + + Windows10 + true + 2 + + + Windows10 + false + 2 + + + Windows10 + true + 2 + + + Windows10 + false + 2 + + + Windows10 + true + 2 + + + Windows10 + false + 2 + + + + + + + + + + DbgengRemoteDebugger + + + DbgengRemoteDebugger + + + DbgengRemoteDebugger + + + DbgengRemoteDebugger + + + DbgengRemoteDebugger + + + DbgengRemoteDebugger + + + DbgengRemoteDebugger + + + DbgengRemoteDebugger + + + + true + true + trace.h + + + + + true + true + trace.h + + + + + true + true + trace.h + + + + + true + true + trace.h + + + + + true + true + trace.h + + + + + true + true + trace.h + + + + + true + true + trace.h + + + + + true + true + trace.h + + + + + + + + + \ No newline at end of file diff --git a/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.vcxproj.filters b/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.vcxproj.filters new file mode 100644 index 00000000..6f2263ef --- /dev/null +++ b/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.vcxproj.filters @@ -0,0 +1,57 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {8E41214B-6785-4CFE-B992-037D68949A14} + inf;inv;inx;mof;mc; + + + + + + + + Driver Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/general/SimpleMediaSource/SimpleMediaSourceDriver/Trace.h b/general/SimpleMediaSource/SimpleMediaSourceDriver/Trace.h new file mode 100644 index 00000000..0180b817 --- /dev/null +++ b/general/SimpleMediaSource/SimpleMediaSourceDriver/Trace.h @@ -0,0 +1,62 @@ +/*++ + +Module Name: + + Internal.h + +Abstract: + + This module contains the local type definitions for the + driver. + +Environment: + + Windows User-Mode Driver Framework 2 + +--*/ + +// +// Define the tracing flags. +// +// Tracing GUID - a9ae54d8-0a84-4b05-b9ae-faff98267b7e +// + +#define WPP_CONTROL_GUIDS \ + WPP_DEFINE_CONTROL_GUID( \ + MyDriver1TraceGuid, (a9ae54d8,0a84,4b05,b9ae,faff98267b7e), \ + \ + WPP_DEFINE_BIT(MYDRIVER_ALL_INFO) \ + WPP_DEFINE_BIT(TRACE_DRIVER) \ + WPP_DEFINE_BIT(TRACE_DEVICE) \ + WPP_DEFINE_BIT(TRACE_QUEUE) \ + ) + +#define WPP_FLAG_LEVEL_LOGGER(flag, level) \ + WPP_LEVEL_LOGGER(flag) + +#define WPP_FLAG_LEVEL_ENABLED(flag, level) \ + (WPP_LEVEL_ENABLED(flag) && \ + WPP_CONTROL(WPP_BIT_ ## flag).Level >= level) + +#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) \ + WPP_LEVEL_LOGGER(flags) + +#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) \ + (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl) + +// +// This comment block is scanned by the trace preprocessor to define our +// Trace function. +// +// begin_wpp config +// FUNC Trace{FLAG=MYDRIVER_ALL_INFO}(LEVEL, MSG, ...); +// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...); +// end_wpp + +// +// +// Driver specific #defines +// +#if UMDF_VERSION_MAJOR == 2 && UMDF_VERSION_MINOR == 0 + #define MYDRIVER_TRACING_ID L"Microsoft\\UMDF2.0\\SimpleMediaSourceDriver V1.0" +#endif \ No newline at end of file -- cgit v1.3.1 From 2649a6ac6d3edbe2eea9a9e4b6a0168da6609b3a Mon Sep 17 00:00:00 2001 From: Peihsun Yeh Date: Wed, 15 Aug 2018 15:15:19 -0700 Subject: adding entry code for media source --- general/SimpleMediaSource/MediaSource/MediaSource.vcxproj | 9 +++++++++ .../SimpleMediaSource/MediaSource/MediaSource.vcxproj.filters | 3 +++ general/SimpleMediaSource/SimpleMediaSourceDriver/Device.c | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) (limited to 'general/SimpleMediaSource') diff --git a/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj b/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj index ea726a92..15e2b6c8 100644 --- a/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj +++ b/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj @@ -80,6 +80,8 @@ mfplat.lib;RuntimeObject.lib;Mfsensorgroup.lib;%(AdditionalDependencies) + %(IgnoreSpecificDefaultLibraries) + $(SolutionDir)MediaSource\module.def @@ -91,6 +93,8 @@ mfplat.lib;RuntimeObject.lib;Mfsensorgroup.lib;%(AdditionalDependencies) + $(SolutionDir)MediaSource\module.def + %(IgnoreSpecificDefaultLibraries) @@ -106,6 +110,8 @@ true true mfplat.lib;RuntimeObject.lib;Mfsensorgroup.lib;%(AdditionalDependencies) + %(IgnoreSpecificDefaultLibraries) + $(SolutionDir)MediaSource\module.def @@ -121,12 +127,15 @@ true true mfplat.lib;RuntimeObject.lib;Mfsensorgroup.lib;%(AdditionalDependencies) + %(IgnoreSpecificDefaultLibraries) + $(SolutionDir)MediaSource\module.def + diff --git a/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj.filters b/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj.filters index ce4a1433..ffcc9853 100644 --- a/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj.filters +++ b/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj.filters @@ -29,6 +29,9 @@ Source Files + + Source Files + diff --git a/general/SimpleMediaSource/SimpleMediaSourceDriver/Device.c b/general/SimpleMediaSource/SimpleMediaSourceDriver/Device.c index 0cf7979e..2fa03bb9 100644 --- a/general/SimpleMediaSource/SimpleMediaSourceDriver/Device.c +++ b/general/SimpleMediaSource/SimpleMediaSourceDriver/Device.c @@ -75,7 +75,7 @@ Return Value: // status = WdfDeviceCreateDeviceInterface( device, - &GUID_DEVINTERFACE_SimpleMediaSourceDriver, + &CAMERA_CATEGORY, NULL // ReferenceString ); -- cgit v1.3.1 From 039691b8fcc20ff71815ebae5848a0c0da8aaa75 Mon Sep 17 00:00:00 2001 From: Joel Corley Date: Fri, 17 Aug 2018 17:23:35 -0700 Subject: Fix the solution and project so everything builds. Note: The DLLs are still not being signed. The driver package will install, but won't start because of it. --- .../MediaSource/MediaSource.vcxproj | 200 +++++++++++++++++++-- general/SimpleMediaSource/SimpleMediaSource.sln | 8 +- .../SimpleMediaSourceDriver.vcxproj | 50 +++++- 3 files changed, 242 insertions(+), 16 deletions(-) (limited to 'general/SimpleMediaSource') diff --git a/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj b/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj index 15e2b6c8..47562ff7 100644 --- a/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj +++ b/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj @@ -1,10 +1,26 @@ + + Debug + ARM + + + Debug + ARM64 + Debug Win32 + + Release + ARM + + + Release + ARM64 + Release Win32 @@ -22,35 +38,69 @@ 15.0 {43AD9BF7-E765-48FE-9826-71A8F2CB12DD} MediaSource - 10.0.17134.0 + $(LatestTargetPlatformVersion) SimpleMediaSource DynamicLibrary true - v141 + WindowsApplicationForDrivers10.0 + MultiByte + Universal + + + DynamicLibrary + true + WindowsApplicationForDrivers10.0 MultiByte + Universal DynamicLibrary false - v141 + WindowsApplicationForDrivers10.0 true MultiByte + Universal + + + DynamicLibrary + false + WindowsApplicationForDrivers10.0 + true + MultiByte + Universal DynamicLibrary true - v141 + WindowsApplicationForDrivers10.0 + MultiByte + Universal + + + DynamicLibrary + true + WindowsApplicationForDrivers10.0 MultiByte + Universal DynamicLibrary false - v141 + WindowsApplicationForDrivers10.0 true MultiByte + Universal + + + DynamicLibrary + false + WindowsApplicationForDrivers10.0 + true + MultiByte + Universal @@ -60,26 +110,88 @@ + + + + + + + + + + + + - + + NativeRecommendedRules.ruleset + false + + + NativeRecommendedRules.ruleset + false + + + NativeRecommendedRules.ruleset + false + + + NativeRecommendedRules.ruleset + false + + + NativeRecommendedRules.ruleset + false + + + NativeRecommendedRules.ruleset + false + + + NativeRecommendedRules.ruleset + false + + + NativeRecommendedRules.ruleset + false + Level3 Disabled true true + false + false + MultiThreadedDebugDLL + + + mfplat.lib;Mfsensorgroup.lib;%(AdditionalDependencies);OneCoreUAP.lib + %(IgnoreSpecificDefaultLibraries) + $(SolutionDir)MediaSource\module.def + + + + + Level3 + Disabled + true + true + false + false + MultiThreadedDebugDLL - mfplat.lib;RuntimeObject.lib;Mfsensorgroup.lib;%(AdditionalDependencies) + mfplat.lib;Mfsensorgroup.lib;%(AdditionalDependencies);OneCoreUAP.lib %(IgnoreSpecificDefaultLibraries) $(SolutionDir)MediaSource\module.def @@ -90,9 +202,28 @@ Disabled true true + false + false + MultiThreadedDebugDLL + + + mfplat.lib;Mfsensorgroup.lib;%(AdditionalDependencies);OneCoreUAP.lib + $(SolutionDir)MediaSource\module.def + %(IgnoreSpecificDefaultLibraries) + + + + + Level3 + Disabled + true + true + false + false + MultiThreadedDebugDLL - mfplat.lib;RuntimeObject.lib;Mfsensorgroup.lib;%(AdditionalDependencies) + mfplat.lib;Mfsensorgroup.lib;%(AdditionalDependencies);OneCoreUAP.lib $(SolutionDir)MediaSource\module.def %(IgnoreSpecificDefaultLibraries) @@ -105,13 +236,39 @@ true true true + false + false + MultiThreadedDLL true true - mfplat.lib;RuntimeObject.lib;Mfsensorgroup.lib;%(AdditionalDependencies) + mfplat.lib;Mfsensorgroup.lib;%(AdditionalDependencies);OneCoreUAP.lib %(IgnoreSpecificDefaultLibraries) $(SolutionDir)MediaSource\module.def + + + + + + Level3 + MaxSpeed + true + true + true + true + false + false + MultiThreadedDLL + + + true + true + mfplat.lib;Mfsensorgroup.lib;%(AdditionalDependencies);OneCoreUAP.lib + %(IgnoreSpecificDefaultLibraries) + $(SolutionDir)MediaSource\module.def + + @@ -122,11 +279,34 @@ true true true + false + MultiThreadedDLL + false + + + true + true + mfplat.lib;Mfsensorgroup.lib;%(AdditionalDependencies);OneCoreUAP.lib + %(IgnoreSpecificDefaultLibraries) + $(SolutionDir)MediaSource\module.def + + + + + Level3 + MaxSpeed + true + true + true + true + false + MultiThreadedDLL + false true true - mfplat.lib;RuntimeObject.lib;Mfsensorgroup.lib;%(AdditionalDependencies) + mfplat.lib;Mfsensorgroup.lib;%(AdditionalDependencies);OneCoreUAP.lib %(IgnoreSpecificDefaultLibraries) $(SolutionDir)MediaSource\module.def diff --git a/general/SimpleMediaSource/SimpleMediaSource.sln b/general/SimpleMediaSource/SimpleMediaSource.sln index c7b0e366..c93b8c42 100644 --- a/general/SimpleMediaSource/SimpleMediaSource.sln +++ b/general/SimpleMediaSource/SimpleMediaSource.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.27703.2026 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MediaSource", "MediaSource\MediaSource.vcxproj", "{43AD9BF7-E765-48FE-9826-71A8F2CB12DD}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleMediaSource", "MediaSource\MediaSource.vcxproj", "{43AD9BF7-E765-48FE-9826-71A8F2CB12DD}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleMediaSourceDriver", "SimpleMediaSourceDriver\SimpleMediaSourceDriver.vcxproj", "{3098C6BF-E96E-4793-A70E-FB09B741580A}" EndProject @@ -25,8 +25,10 @@ Global {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Debug|x64.Build.0 = Debug|x64 {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Debug|x86.ActiveCfg = Debug|Win32 {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Debug|x86.Build.0 = Debug|Win32 - {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Release|ARM.ActiveCfg = Release|Win32 - {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Release|ARM64.ActiveCfg = Release|Win32 + {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Release|ARM.ActiveCfg = Release|ARM + {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Release|ARM.Build.0 = Release|ARM + {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Release|ARM64.ActiveCfg = Release|ARM64 + {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Release|ARM64.Build.0 = Release|ARM64 {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Release|x64.ActiveCfg = Release|x64 {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Release|x64.Build.0 = Release|x64 {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Release|x86.ActiveCfg = Release|Win32 diff --git a/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.vcxproj b/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.vcxproj index c3afadf5..38e21ccd 100644 --- a/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.vcxproj +++ b/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.vcxproj @@ -52,6 +52,21 @@ + + + + + + + + + + + + + {43ad9bf7-e765-48fe-9826-71a8f2cb12dd} + + {3098C6BF-E96E-4793-A70E-FB09B741580A} {32909489-7be5-497b-aafa-db6669d9b44b} @@ -163,15 +178,23 @@ DbgengRemoteDebugger + false + + DbgengRemoteDebugger + false + + DbgengRemoteDebugger + Server10_$(DDKPlatform) DbgengRemoteDebugger + Server10_$(DDKPlatform) @@ -179,6 +202,9 @@ true trace.h + + %(AdditionalDependencies);$(SDK_LIB_PATH)\OneCoreUAP.lib + @@ -186,6 +212,9 @@ true trace.h + + %(AdditionalDependencies);$(SDK_LIB_PATH)\OneCoreUAP.lib + @@ -193,6 +222,9 @@ true trace.h + + %(AdditionalDependencies);$(SDK_LIB_PATH)\OneCoreUAP.lib + @@ -200,6 +232,9 @@ true trace.h + + %(AdditionalDependencies);$(SDK_LIB_PATH)\OneCoreUAP.lib + @@ -207,6 +242,9 @@ true trace.h + + %(AdditionalDependencies);$(SDK_LIB_PATH)\OneCoreUAP.lib + @@ -214,6 +252,9 @@ true trace.h + + %(AdditionalDependencies);$(SDK_LIB_PATH)\OneCoreUAP.lib + @@ -221,6 +262,9 @@ true trace.h + + %(AdditionalDependencies);$(SDK_LIB_PATH)\OneCoreUAP.lib + @@ -228,10 +272,10 @@ true trace.h + + %(AdditionalDependencies);$(SDK_LIB_PATH)\OneCoreUAP.lib + - - - -- cgit v1.3.1 From 6930fc413a7a19ce04fb61fab5db7e71729fde18 Mon Sep 17 00:00:00 2001 From: Peihsun Yeh Date: Fri, 24 Aug 2018 14:58:59 -0700 Subject: added mising referencestring --- general/SimpleMediaSource/SimpleMediaSourceDriver/Device.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'general/SimpleMediaSource') diff --git a/general/SimpleMediaSource/SimpleMediaSourceDriver/Device.c b/general/SimpleMediaSource/SimpleMediaSourceDriver/Device.c index 2fa03bb9..133d55eb 100644 --- a/general/SimpleMediaSource/SimpleMediaSourceDriver/Device.c +++ b/general/SimpleMediaSource/SimpleMediaSourceDriver/Device.c @@ -47,6 +47,8 @@ Return Value: PDEVICE_CONTEXT deviceContext; WDFDEVICE device; NTSTATUS status; + UNICODE_STRING szReference; + RtlInitUnicodeString(&szReference, L"CustomCameraSource"); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT); @@ -76,7 +78,7 @@ Return Value: status = WdfDeviceCreateDeviceInterface( device, &CAMERA_CATEGORY, - NULL // ReferenceString + &szReference // ReferenceString ); if (NT_SUCCESS(status)) { @@ -87,7 +89,7 @@ Return Value: status = WdfDeviceCreateDeviceInterface( device, &CAPTURE_CATEGORY, - NULL // ReferenceString + &szReference // ReferenceString ); } @@ -99,7 +101,7 @@ Return Value: status = WdfDeviceCreateDeviceInterface( device, &VIDEO_CATEGORY, - NULL // ReferenceString + &szReference // ReferenceString ); } -- cgit v1.3.1 From 28c11cc0153286544abdb66eac22c760b73a4155 Mon Sep 17 00:00:00 2001 From: Peihsun Yeh Date: Mon, 27 Aug 2018 11:13:03 -0700 Subject: clarifying comments, removing some also --- general/SimpleMediaSource/SimpleMediaSourceDriver/Device.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'general/SimpleMediaSource') diff --git a/general/SimpleMediaSource/SimpleMediaSourceDriver/Device.c b/general/SimpleMediaSource/SimpleMediaSourceDriver/Device.c index 133d55eb..083cf3c7 100644 --- a/general/SimpleMediaSource/SimpleMediaSourceDriver/Device.c +++ b/general/SimpleMediaSource/SimpleMediaSourceDriver/Device.c @@ -48,7 +48,7 @@ Return Value: WDFDEVICE device; NTSTATUS status; UNICODE_STRING szReference; - RtlInitUnicodeString(&szReference, L"CustomCameraSource"); + RtlInitUnicodeString(&szReference, L"CustomCameraSource"); // Needs to match the ReferenceString in INF WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT); @@ -82,10 +82,6 @@ Return Value: ); if (NT_SUCCESS(status)) { - // - // Create a device interface so that application can find and talk - // to us. - // status = WdfDeviceCreateDeviceInterface( device, &CAPTURE_CATEGORY, @@ -94,10 +90,6 @@ Return Value: } if (NT_SUCCESS(status)) { - // - // Create a device interface so that application can find and talk - // to us. - // status = WdfDeviceCreateDeviceInterface( device, &VIDEO_CATEGORY, -- cgit v1.3.1 From 080cc41332f5f1cddd8ace680f74a8b374e463b7 Mon Sep 17 00:00:00 2001 From: Peihsun Yeh Date: Fri, 7 Sep 2018 14:13:20 -0700 Subject: fix bug in source not allowing to go from shutdown to start --- general/SimpleMediaSource/MediaSource/SimpleMediaSource.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'general/SimpleMediaSource') diff --git a/general/SimpleMediaSource/MediaSource/SimpleMediaSource.cpp b/general/SimpleMediaSource/MediaSource/SimpleMediaSource.cpp index 1729fbcf..162fb1d8 100644 --- a/general/SimpleMediaSource/MediaSource/SimpleMediaSource.cpp +++ b/general/SimpleMediaSource/MediaSource/SimpleMediaSource.cpp @@ -199,7 +199,7 @@ SimpleMediaSource::Start( RETURN_IF_FAILED (_CheckShutdownRequiresLock()); - if (_sourceState != SourceState::Stopped) + if (!(_sourceState != SourceState::Stopped || _sourceState != SourceState::Shutdown)) { return MF_E_INVALID_STATE_TRANSITION; } @@ -277,6 +277,8 @@ SimpleMediaSource::Stop( return MF_E_INVALID_STATE_TRANSITION; } + _sourceState = SourceState::Stopped; + RETURN_IF_FAILED (_CheckShutdownRequiresLock()); RETURN_IF_FAILED (InitPropVariantFromInt64(MFGetSystemTime(), &stopTime)); RETURN_IF_FAILED (_spPresentationDescriptor->GetStreamDescriptorCount(&count)); -- cgit v1.3.1 From 6e4385c5a55e829863cb781ffccc002c961dcf06 Mon Sep 17 00:00:00 2001 From: Peihsun Yeh Date: Wed, 2 Jan 2019 17:17:26 -0800 Subject: Adding README and yaml --- general/SimpleMediaSource/README.md | 34 ++++++++++++++++++++++ .../general-SimpleMediaSource.yaml | 10 +++++++ 2 files changed, 44 insertions(+) create mode 100644 general/SimpleMediaSource/README.md create mode 100644 general/SimpleMediaSource/general-SimpleMediaSource.yaml (limited to 'general/SimpleMediaSource') diff --git a/general/SimpleMediaSource/README.md b/general/SimpleMediaSource/README.md new file mode 100644 index 00000000..509edf47 --- /dev/null +++ b/general/SimpleMediaSource/README.md @@ -0,0 +1,34 @@ + + +SimpleMediaSource Sample +======================== +This sample demonstrates how to create a custom media source and driver package that can be installed as a Camera and produce frames. + +This sample has accompanying documentation here: https://docs.microsoft.com/en-us/windows-hardware/drivers/stream/frame-server-custom-media-source + + +Contents +-------- +MediaSource - COM DLL project for the custom media source + +SimpleMediaSourceDriver - UMDF driver install package + +Installation +------------------ + +1. Build the solution. + +2. Navigate to the output folder, e.g. Windows-driver-samples\general\SimpleMediaSource\x64\Release, and the driver package will be in a directory also called SimpleMediaSourceDriver. Check that the folder has `SimpleMediaSource.dll`, `simplemediasourcedriver.cat`, `SimpleMediaSourceDriver.dll`, and `SimpleMediaSourceDriver.inf`. + +3. Deploy the driver package with + +`devcon dp_add SimpleMediaSourceDriver.inf` + +4. In Device Manager, locate **SimpleMediaSource Capture Source**, under the Camera category. Open the Microsoft Camera App, switch cameras if necessary until the camera is streaming from the SimpleMediaSource. You should see a scrolling black and white gradient. \ No newline at end of file diff --git a/general/SimpleMediaSource/general-SimpleMediaSource.yaml b/general/SimpleMediaSource/general-SimpleMediaSource.yaml new file mode 100644 index 00000000..88e2d839 --- /dev/null +++ b/general/SimpleMediaSource/general-SimpleMediaSource.yaml @@ -0,0 +1,10 @@ +### YamlMime:Sample +sample: +- name: SimpleMediaSource Sample + description: Demonstrates how to write a custom media source and driver package. + generateZip: true + author: windows-driver-samples + languages: + - cpp + technologies: + - windows -- cgit v1.3.1 From 94f38da770fd3c00e4ee62c983d92c769c80c6c9 Mon Sep 17 00:00:00 2001 From: Peihsun Yeh Date: Wed, 2 Jan 2019 17:56:43 -0800 Subject: Updating readme category --- general/SimpleMediaSource/README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'general/SimpleMediaSource') diff --git a/general/SimpleMediaSource/README.md b/general/SimpleMediaSource/README.md index 509edf47..ca8e85da 100644 --- a/general/SimpleMediaSource/README.md +++ b/general/SimpleMediaSource/README.md @@ -1,8 +1,8 @@ @@ -17,7 +17,6 @@ This sample has accompanying documentation here: https://docs.microsoft.com/en-u Contents -------- MediaSource - COM DLL project for the custom media source - SimpleMediaSourceDriver - UMDF driver install package Installation -- cgit v1.3.1