diff options
| author | Peihsun Yeh <[email protected]> | 2018-08-01 16:58:31 -0700 |
|---|---|---|
| committer | Peihsun Yeh <[email protected]> | 2018-08-01 16:58:31 -0700 |
| commit | edcb51e041d612e3fb8a0c0a9135d989c881ccc9 (patch) | |
| tree | c30b3e38242aac68061556481ddace96bee1a9ca /general/SimpleMediaSource | |
| parent | a49f6121e1976979af7d6d8fc1f9af7acec9bcb2 (diff) | |
Creating custom media source solution and project (still needs driver)
Diffstat (limited to 'general/SimpleMediaSource')
11 files changed, 1390 insertions, 0 deletions
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 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <VCProjectVersion>15.0</VCProjectVersion> + <ProjectGuid>{43AD9BF7-E765-48FE-9826-71A8F2CB12DD}</ProjectGuid> + <RootNamespace>MediaSource</RootNamespace> + <WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v141</PlatformToolset> + <CharacterSet>MultiByte</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v141</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>MultiByte</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v141</PlatformToolset> + <CharacterSet>MultiByte</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>v141</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>MultiByte</CharacterSet> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="Shared"> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup /> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <SDLCheck>true</SDLCheck> + <ConformanceMode>true</ConformanceMode> + </ClCompile> + <Link> + <AdditionalDependencies>mfplat.lib;RuntimeObject.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <SDLCheck>true</SDLCheck> + <ConformanceMode>true</ConformanceMode> + </ClCompile> + <Link> + <AdditionalDependencies>mfplat.lib;RuntimeObject.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + <ConformanceMode>true</ConformanceMode> + </ClCompile> + <Link> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <AdditionalDependencies>mfplat.lib;RuntimeObject.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + <ConformanceMode>true</ConformanceMode> + </ClCompile> + <Link> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <AdditionalDependencies>mfplat.lib;RuntimeObject.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <None Include="module.def" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="SimpleMediaSource.cpp" /> + <ClCompile Include="SimpleMediaStream.cpp" /> + <ClCompile Include="stdafx.cpp" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="SimpleMediaSource.h" /> + <ClInclude Include="SimpleMediaStream.h" /> + <ClInclude Include="stdafx.h" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ 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 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> + </Filter> + </ItemGroup> + <ItemGroup> + <None Include="module.def"> + <Filter>Source Files</Filter> + </None> + </ItemGroup> + <ItemGroup> + <ClCompile Include="SimpleMediaSource.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="SimpleMediaStream.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="stdafx.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="SimpleMediaSource.h"> + <Filter>Source Files</Filter> + </ClInclude> + <ClInclude Include="SimpleMediaStream.h"> + <Filter>Source Files</Filter> + </ClInclude> + <ClInclude Include="stdafx.h"> + <Filter>Source Files</Filter> + </ClInclude> + </ItemGroup> +</Project>
\ 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<SimpleMediaStream>(&_stream, this); + } + + if (SUCCEEDED(hr)) + { + ComPtr<IMFStreamDescriptor> 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<IMFMediaEventQueue> 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<IMFStreamDescriptor> 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<IUnknown> 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<IMFStreamDescriptor> 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<WinRtClassicComMix>, + 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<IMFMediaEventQueue> _spEventQueue; + ComPtr<IMFPresentationDescriptor> _spPresentationDescriptor; + ComPtr<IMFAttributes> _spAttributes; + + bool _wasStreamPreviouslySelected; // maybe makes more sense as a property of the stream + const DWORD NUM_STREAMS = 1; + ComPtr<SimpleMediaStream> _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<IMFMediaTypeHandler> spTypeHandler; + ComPtr<IMFAttributes> 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<IMFMediaEventQueue> 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<SimpleMediaSource> 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<IMFSample> spSample; + + ComPtr<IMFMediaBuffer> 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<IMF2DBuffer2> 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<ClassicCom>, + 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<IMFMediaEventQueue> _spEventQueue; + ComPtr<IMFAttributes> _spAttributes; + ComPtr<IMFMediaType> _spMediaType; + ComPtr<IMFStreamDescriptor> _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 file="dllmain.cpp" company="Microsoft"> +/// Copyright (c) Microsoft Corporation. All rights reserved. +/// </copyright> +// dllmain.cpp : Defines the entry point for the DLL application. +#include "stdafx.h" + +#include <wrl\module.h> + +#if !defined(__WRL_CLASSIC_COM__) +STDAPI DllGetActivationFactory(_In_ HSTRING activatibleClassId, _COM_Outptr_ IActivationFactory** factory) +{ + return Module<InProc>::GetModule().GetActivationFactory(activatibleClassId, factory); +} +#endif + +#if !defined(__WRL_WINRT_STRICT__) +STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, _COM_Outptr_ void** ppv) +{ + return Module<InProc>::GetModule().GetClassObject(rclsid, riid, ppv); +} +#endif + +STDAPI DllCanUnloadNow() +{ + return Module<InProc>::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 file="stdafx.cpp" company="Microsoft"> +/// Copyright (c) Microsoft Corporation. All rights reserved. +/// </copyright> +// 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 <windows.h> +#include <minwindef.h> +#include <ks.h> +#include <propvarutil.h> +//#include <mfstd.h> // Must be included before <initguid.h>, or else DirectDraw GUIDs will be defined twice. See the comment in <uuids.h>. +#include <ole2.h> +#include <initguid.h> +#include <mfapi.h> +#include <mferror.h> +#include <mfidl.h> +#include <mfreadwrite.h> +#include <nserror.h> +#include <winmeta.h> +#include <wrl.h> +#include <d3d9types.h> +#include <ksmedia.h> + +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 |
