summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--general/SimpleMediaSource/MediaSource/MediaSource.vcxproj76
-rw-r--r--general/SimpleMediaSource/MediaSource/MediaSource.vcxproj.filters22
-rw-r--r--general/SimpleMediaSource/MediaSource/SimpleFrameGenerator.cpp146
-rw-r--r--general/SimpleMediaSource/MediaSource/SimpleFrameGenerator.h46
-rw-r--r--general/SimpleMediaSource/MediaSource/SimpleMediaSource.cpp925
-rw-r--r--general/SimpleMediaSource/MediaSource/SimpleMediaSource.h169
-rw-r--r--general/SimpleMediaSource/MediaSource/SimpleMediaSourceActivate.cpp245
-rw-r--r--general/SimpleMediaSource/MediaSource/SimpleMediaSourceActivate.h82
-rw-r--r--general/SimpleMediaSource/MediaSource/SimpleMediaStream.cpp610
-rw-r--r--general/SimpleMediaSource/MediaSource/SimpleMediaStream.h93
-rw-r--r--general/SimpleMediaSource/MediaSource/dllMain.cpp67
-rw-r--r--general/SimpleMediaSource/MediaSource/module.def5
-rw-r--r--general/SimpleMediaSource/MediaSource/pch.cpp26
-rw-r--r--general/SimpleMediaSource/MediaSource/pch.h82
-rw-r--r--general/SimpleMediaSource/MediaSource/stdafx.cpp11
-rw-r--r--general/SimpleMediaSource/MediaSource/stdafx.h76
-rw-r--r--general/SimpleMediaSource/SimpleMediaSource.sln4
-rw-r--r--general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.vcxproj13
18 files changed, 1760 insertions, 938 deletions
diff --git a/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj b/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj
index 47562ff7..3c5ff0de 100644
--- a/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj
+++ b/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj
@@ -53,7 +53,7 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
- <CharacterSet>MultiByte</CharacterSet>
+ <CharacterSet>Unicode</CharacterSet>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
@@ -61,7 +61,7 @@
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <CharacterSet>MultiByte</CharacterSet>
+ <CharacterSet>Unicode</CharacterSet>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
@@ -69,21 +69,20 @@
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <CharacterSet>MultiByte</CharacterSet>
+ <CharacterSet>Unicode</CharacterSet>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
- <CharacterSet>MultiByte</CharacterSet>
- <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
- <CharacterSet>MultiByte</CharacterSet>
+ <CharacterSet>Unicode</CharacterSet>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
@@ -91,15 +90,16 @@
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <CharacterSet>MultiByte</CharacterSet>
+ <CharacterSet>Unicode</CharacterSet>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <Driver_SpectreMitigation>Spectre</Driver_SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <CharacterSet>MultiByte</CharacterSet>
+ <CharacterSet>Unicode</CharacterSet>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
@@ -171,8 +171,13 @@
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<EnablePREfast>false</EnablePREfast>
- <ExceptionHandling>false</ExceptionHandling>
+ <ExceptionHandling>Sync</ExceptionHandling>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <LanguageStandard>stdcpp17</LanguageStandard>
+ <CallingConvention>Cdecl</CallingConvention>
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
+ <AdditionalIncludeDirectories>..\..\..\wil\include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>mfplat.lib;Mfsensorgroup.lib;%(AdditionalDependencies);OneCoreUAP.lib</AdditionalDependencies>
@@ -187,8 +192,12 @@
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<EnablePREfast>false</EnablePREfast>
- <ExceptionHandling>false</ExceptionHandling>
+ <ExceptionHandling>Sync</ExceptionHandling>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <LanguageStandard>stdcpp17</LanguageStandard>
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
+ <AdditionalIncludeDirectories>..\..\..\wil\include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>mfplat.lib;Mfsensorgroup.lib;%(AdditionalDependencies);OneCoreUAP.lib</AdditionalDependencies>
@@ -203,8 +212,12 @@
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<EnablePREfast>false</EnablePREfast>
- <ExceptionHandling>false</ExceptionHandling>
+ <ExceptionHandling>Sync</ExceptionHandling>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <LanguageStandard>stdcpp17</LanguageStandard>
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
+ <AdditionalIncludeDirectories>..\..\..\wil\include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>mfplat.lib;Mfsensorgroup.lib;%(AdditionalDependencies);OneCoreUAP.lib</AdditionalDependencies>
@@ -219,8 +232,12 @@
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<EnablePREfast>false</EnablePREfast>
- <ExceptionHandling>false</ExceptionHandling>
+ <ExceptionHandling>Sync</ExceptionHandling>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <LanguageStandard>stdcpp17</LanguageStandard>
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
+ <AdditionalIncludeDirectories>..\..\..\wil\include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>mfplat.lib;Mfsensorgroup.lib;%(AdditionalDependencies);OneCoreUAP.lib</AdditionalDependencies>
@@ -237,8 +254,12 @@
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<EnablePREfast>false</EnablePREfast>
- <ExceptionHandling>false</ExceptionHandling>
+ <ExceptionHandling>Sync</ExceptionHandling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <LanguageStandard>stdcpp17</LanguageStandard>
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
+ <AdditionalIncludeDirectories>..\..\..\wil\include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
@@ -258,8 +279,12 @@
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<EnablePREfast>false</EnablePREfast>
- <ExceptionHandling>false</ExceptionHandling>
+ <ExceptionHandling>Sync</ExceptionHandling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <LanguageStandard>stdcpp17</LanguageStandard>
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
+ <AdditionalIncludeDirectories>..\..\..\wil\include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
@@ -281,7 +306,11 @@
<ConformanceMode>true</ConformanceMode>
<EnablePREfast>false</EnablePREfast>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
- <ExceptionHandling>false</ExceptionHandling>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <LanguageStandard>stdcpp17</LanguageStandard>
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
+ <AdditionalIncludeDirectories>..\..\..\wil\include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
@@ -301,7 +330,11 @@
<ConformanceMode>true</ConformanceMode>
<EnablePREfast>false</EnablePREfast>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
- <ExceptionHandling>false</ExceptionHandling>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <LanguageStandard>stdcpp17</LanguageStandard>
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
+ <AdditionalIncludeDirectories>..\..\..\wil\include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
@@ -316,16 +349,19 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllMain.cpp" />
+ <ClCompile Include="SimpleFrameGenerator.cpp" />
<ClCompile Include="SimpleMediaSource.cpp" />
+ <ClCompile Include="SimpleMediaSourceActivate.cpp" />
<ClCompile Include="SimpleMediaStream.cpp" />
- <ClCompile Include="stdafx.cpp" />
+ <ClCompile Include="pch.cpp" />
</ItemGroup>
<ItemGroup>
+ <ClInclude Include="SimpleFrameGenerator.h" />
<ClInclude Include="SimpleMediaSource.h" />
+ <ClInclude Include="SimpleMediaSourceActivate.h" />
<ClInclude Include="SimpleMediaStream.h" />
- <ClInclude Include="stdafx.h" />
+ <ClInclude Include="pch.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
- <ImportGroup Label="ExtensionTargets">
- </ImportGroup>
+ <ImportGroup Label="ExtensionTargets" />
</Project> \ No newline at end of file
diff --git a/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj.filters b/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj.filters
index ffcc9853..ba0d78a1 100644
--- a/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj.filters
+++ b/general/SimpleMediaSource/MediaSource/MediaSource.vcxproj.filters
@@ -26,22 +26,34 @@
<ClCompile Include="SimpleMediaStream.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="stdafx.cpp">
+ <ClCompile Include="pch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="dllMain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="SimpleMediaSourceActivate.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="SimpleFrameGenerator.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="SimpleMediaSource.h">
- <Filter>Source Files</Filter>
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="SimpleMediaSourceActivate.h">
+ <Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="SimpleMediaStream.h">
- <Filter>Source Files</Filter>
+ <Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="stdafx.h">
- <Filter>Source Files</Filter>
+ <ClInclude Include="pch.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="SimpleFrameGenerator.h">
+ <Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/general/SimpleMediaSource/MediaSource/SimpleFrameGenerator.cpp b/general/SimpleMediaSource/MediaSource/SimpleFrameGenerator.cpp
new file mode 100644
index 00000000..6adafb44
--- /dev/null
+++ b/general/SimpleMediaSource/MediaSource/SimpleFrameGenerator.cpp
@@ -0,0 +1,146 @@
+//
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+#include "pch.h"
+
+HRESULT SimpleFrameGenerator::Initialize(_In_ IMFMediaType* pMediaType)
+{
+ RETURN_HR_IF_NULL(E_INVALIDARG, pMediaType);
+
+ RETURN_IF_FAILED(pMediaType->GetGUID(MF_MT_SUBTYPE, &m_subType));
+ if (m_subType != MFVideoFormat_RGB32 && m_subType != MFVideoFormat_NV12)
+ {
+ RETURN_HR_MSG(MF_E_UNSUPPORTED_FORMAT, "Unsupported format: %s", winrt::to_hstring(m_subType).data());
+ }
+ MFGetAttributeSize(pMediaType, MF_MT_FRAME_SIZE, &m_width, &m_height);
+
+ return S_OK;
+}
+
+/*:
+ 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 SimpleFrameGenerator::CreateFrame(
+ _Inout_updates_bytes_(len) BYTE* pBuf,
+ _In_ DWORD len,
+ _In_ LONG pitch,
+ _In_ ULONG rgbMask)
+{
+ if (m_subType == MFVideoFormat_RGB32)
+ {
+ DEBUG_MSG(L"RGB32 frames %s\n", winrt::to_hstring(MFVideoFormat_RGB32).data());
+
+ RETURN_IF_FAILED(_CreateRGB32Frame(pBuf, len, pitch, m_width, m_height, rgbMask));
+ }
+ else if(m_subType == MFVideoFormat_NV12)
+ {
+ DEBUG_MSG(L"NV12 frames %s \n", winrt::to_hstring(MFVideoFormat_NV12).data());
+
+ DWORD frameBuffLen = m_width * m_height * 4;
+ wil::unique_cotaskmem_ptr<BYTE[]> spBuff = wil::make_unique_cotaskmem_nothrow<BYTE[]>(frameBuffLen);
+ RETURN_IF_NULL_ALLOC(spBuff.get());
+
+ RETURN_IF_FAILED(_CreateRGB32Frame(spBuff.get(), frameBuffLen, m_width * 4, m_width, m_height, rgbMask));
+ RETURN_IF_FAILED(RGB32ToNV12Frame(spBuff.get(), frameBuffLen, m_width * 4, m_width, m_height, pBuf, len, pitch));
+ }
+ else
+ {
+ return MF_E_UNSUPPORTED_FORMAT;
+ }
+
+ return S_OK;
+}
+
+//////////////////////////////////////////////////
+// private
+
+HRESULT SimpleFrameGenerator::_CreateRGB32Frame(
+ _Inout_updates_bytes_(len) BYTE* pBuf,
+ _In_ DWORD len,
+ _In_ LONG pitch,
+ _In_ DWORD width,
+ _In_ DWORD height,
+ _In_ ULONG rgbMask )
+{
+ RETURN_HR_IF_NULL(E_INVALIDARG, pBuf);
+
+ LONGLONG curSysTimeInS = MFGetSystemTime() / (MFTIME)10000000;
+ int offset = curSysTimeInS % height;
+
+ for (unsigned int r = 0; r < height; r++)
+ {
+ uint32_t* p = (uint32_t*)(pBuf + (r * pitch));
+ for (unsigned int c = 0; c < width; c++)
+ {
+ BYTE gray = (BYTE)r + offset;
+ *p = ((uint32_t)gray << 16 | (uint32_t)gray << 8 | (uint32_t)gray) & rgbMask;
+ p++;
+ }
+ }
+
+ return S_OK;
+}
+
+//////////////////////////////////////////////////
+// pixelFormatConverter
+
+void SimpleFrameGenerator::RGB24ToYUY2(int R, int G, int B, BYTE* pY, BYTE* pU, BYTE* pV)
+{
+ *pY = ((66 * R + 129 * G + 25 * B + 128) >> 8) + 16;
+ *pU = ((-38 * R - 74 * G + 112 * B + 128) >> 8) + 128;
+ *pV = ((112 * R - 94 * G - 18 * B + 128) >> 8) + 128;
+}
+
+void SimpleFrameGenerator::RGB24ToY(int R, int G, int B, BYTE* pY)
+{
+ *pY = ((66 * R + 129 * G + 25 * B + 128) >> 8) + 16;
+}
+
+void SimpleFrameGenerator::RGB32ToNV12(BYTE RGB1[8], BYTE RGB2[8], BYTE* pY1, BYTE* pY2, BYTE* pUV)
+{
+ RGB24ToYUY2(RGB1[2], RGB1[1], RGB1[0], pY1, pUV, pUV + 1);
+ RGB24ToY(RGB1[6], RGB1[5], RGB1[4], pY1 + 1);
+ RGB24ToYUY2(RGB2[2], RGB2[1], RGB2[0], pY2, pUV, pUV + 1);
+ RGB24ToY(RGB2[6], RGB2[5], RGB2[4], pY2 + 1);
+};
+
+//////////////////////////////////////////////////
+// FrameFormatConverter
+
+HRESULT SimpleFrameGenerator::RGB32ToNV12Frame(_Inout_updates_bytes_(len) BYTE* pbBuff, ULONG cbBuff, long stride, UINT width, UINT height, BYTE* pbBuffOut, ULONG cbBuffOut, long strideOut)
+{
+ do
+ {
+ RETURN_HR_IF(E_UNEXPECTED, width * 4 * height > cbBuff);
+ RETURN_HR_IF(E_UNEXPECTED, width * 1.5 * height > cbBuffOut);
+ RETURN_HR_IF_NULL(E_INVALIDARG, pbBuff);
+
+ RETURN_HR_IF_NULL(E_INVALIDARG, pbBuffOut);
+ for (DWORD h = 0; h < height - 1; h += 2)
+ {
+ BYTE* pRGB1 = h * stride + pbBuff;
+ BYTE* pRGB2 = (h + 1) * stride + pbBuff;
+ BYTE* pY1 = h * strideOut + pbBuffOut;
+ BYTE* pY2 = (h + 1) * strideOut + pbBuffOut;
+ BYTE* pUV = (h / 2 + height) * strideOut + pbBuffOut;
+
+ for (DWORD w = 0; w < width; w += 2)
+ {
+ RGB32ToNV12(pRGB1, pRGB2, pY1, pY2, pUV);
+ pRGB1 += 8;
+ pRGB2 += 8;
+ pY1 += 2;
+ pY2 += 2;
+ pUV += 2;
+ }
+ }
+ } while (FALSE);
+
+ return S_OK;
+}
diff --git a/general/SimpleMediaSource/MediaSource/SimpleFrameGenerator.h b/general/SimpleMediaSource/MediaSource/SimpleFrameGenerator.h
new file mode 100644
index 00000000..f481ab61
--- /dev/null
+++ b/general/SimpleMediaSource/MediaSource/SimpleFrameGenerator.h
@@ -0,0 +1,46 @@
+//
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+
+#pragma once
+#ifndef SIMPLE_FRAME_GENERATOR_H
+#define SIMPLE_FRAME_GENERATOR_H
+
+class SimpleFrameGenerator
+{
+public:
+ SimpleFrameGenerator() = default;
+ ~SimpleFrameGenerator() {};
+
+ HRESULT Initialize(_In_ IMFMediaType* pMediaType);
+
+ HRESULT CreateFrame(
+ _Inout_updates_bytes_(len) BYTE* pBuf,
+ _In_ DWORD len,
+ _In_ LONG pitch,
+ _In_ ULONG rgbMask);
+
+ // pixel format converter
+ static void RGB24ToYUY2(int R, int G, int B, BYTE* pY, BYTE* pU, BYTE* pV);
+ static void RGB24ToY(int R, int G, int B, BYTE* pY);
+ static void RGB32ToNV12(BYTE RGB1[8], BYTE RGB2[8], BYTE* pY1, BYTE* pY2, BYTE* pUV);
+
+ static HRESULT RGB32ToNV12Frame(_Inout_updates_bytes_(len) BYTE* pbBuff, ULONG cbBuff, long stride, UINT width, UINT height, BYTE* pbBuffOut, ULONG cbBuffOut, long strideOut);
+
+private:
+ HRESULT _CreateRGB32Frame(
+ _Inout_updates_bytes_(len) BYTE* pBuf,
+ _In_ DWORD len,
+ _In_ LONG pitch,
+ _In_ DWORD width,
+ _In_ DWORD height,
+ _In_ ULONG rgbMask);
+
+ UINT32 m_width = 0;
+ UINT32 m_height = 0;
+ GUID m_subType = GUID_NULL;
+
+};
+
+#endif
+
diff --git a/general/SimpleMediaSource/MediaSource/SimpleMediaSource.cpp b/general/SimpleMediaSource/MediaSource/SimpleMediaSource.cpp
index 162fb1d8..8ff15872 100644
--- a/general/SimpleMediaSource/MediaSource/SimpleMediaSource.cpp
+++ b/general/SimpleMediaSource/MediaSource/SimpleMediaSource.cpp
@@ -1,526 +1,651 @@
-#include "stdafx.h"
+//
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+#include "pch.h"
-///////////////////////////////////////////////////////////////////////////////
-HRESULT
-SimpleMediaSource::RuntimeClassInitialize(
- )
+namespace winrt::WindowsSample::implementation
{
- HRESULT hr = S_OK;
-
- RETURN_IF_FAILED (MFCreateAttributes(&_spAttributes, 10));
- RETURN_IF_FAILED (MFCreateEventQueue(&_spEventQueue));
- RETURN_IF_FAILED (MakeAndInitialize<SimpleMediaStream>(&_stream, this));
+ /////////////////////////////////////////////////////////////////////////////////
+ HRESULT SimpleMediaSource::Initialize()
{
- ComPtr<IMFStreamDescriptor> streamDescriptor(_stream.Get()->_spStreamDesc.Get());
- RETURN_IF_FAILED (MFCreatePresentationDescriptor(NUM_STREAMS, streamDescriptor.GetAddressOf(), &_spPresentationDescriptor));
- }
+ winrt::slim_lock_guard lock(m_Lock);
- _wasStreamPreviouslySelected = false;
- _sourceState = SourceState::Stopped;
+ RETURN_IF_FAILED(_CreateSourceAttributes());
+ RETURN_IF_FAILED(MFCreateEventQueue(&m_spEventQueue));
- return hr;
-}
+ m_streamList = wilEx::make_unique_cotaskmem_array<wil::com_ptr_nothrow<SimpleMediaStream>>(NUM_STREAMS);
+ RETURN_IF_NULL_ALLOC(m_streamList.get());
-// IMFMediaEventGenerator methods.
-IFACEMETHODIMP
-SimpleMediaSource::BeginGetEvent(
- _In_ IMFAsyncCallback *pCallback,
- _In_ IUnknown *punkState
- )
-{
- HRESULT hr = S_OK;
- auto lock = _critSec.Lock();
+ wil::unique_cotaskmem_array_ptr<wil::com_ptr_nothrow<IMFStreamDescriptor>> streamDescriptorList = wilEx::make_unique_cotaskmem_array<wil::com_ptr_nothrow<IMFStreamDescriptor>>(NUM_STREAMS);
- RETURN_IF_FAILED (_CheckShutdownRequiresLock());
- RETURN_IF_FAILED (_spEventQueue->BeginGetEvent(pCallback, punkState));
+ // This example showcase one stream (i.e. NUM_STREAMS == 1),
+ // it can be extended to multiple streams by changing NUM_STREAMS
+ for (unsigned int i = 0; i < NUM_STREAMS; i++)
+ {
+ auto ptr = winrt::make_self<SimpleMediaStream>();
+ m_streamList[i] = ptr.detach();
+ RETURN_IF_FAILED(m_streamList[i]->Initialize(this, i, MFSampleAllocatorUsage_UsesProvidedAllocator));
- return hr;
-}
+ RETURN_IF_FAILED(m_streamList[i]->GetStreamDescriptor(&streamDescriptorList[i]));
+ }
-IFACEMETHODIMP
-SimpleMediaSource::EndGetEvent(
- _In_ IMFAsyncResult *pResult,
- _COM_Outptr_ IMFMediaEvent **ppEvent
- )
-{
- HRESULT hr = S_OK;
- auto lock = _critSec.Lock();
+ RETURN_IF_FAILED(MFCreatePresentationDescriptor(m_streamList.size(), streamDescriptorList.get(), &m_spPresentationDescriptor));
- RETURN_IF_FAILED (_CheckShutdownRequiresLock());
- RETURN_IF_FAILED (_spEventQueue->EndGetEvent(pResult, ppEvent));
+ m_sourceState = SourceState::Stopped;
- return hr;
-}
+ return S_OK;
+ }
-IFACEMETHODIMP
-SimpleMediaSource::GetEvent(
- DWORD dwFlags,
- _COM_Outptr_ IMFMediaEvent **ppEvent
- )
-{
- // NOTE:
- // GetEvent can block indefinitely, so we don't hold the lock.
- // This requires some juggling with the event queue pointer.
+ // IMFMediaEventGenerator methods.
+ IFACEMETHODIMP SimpleMediaSource::BeginGetEvent(
+ _In_ IMFAsyncCallback* pCallback,
+ _In_ IUnknown* punkState )
+ {
+ winrt::slim_lock_guard lock(m_Lock);
- HRESULT hr = S_OK;
+ RETURN_IF_FAILED(_CheckShutdownRequiresLock());
+ RETURN_IF_FAILED(m_spEventQueue->BeginGetEvent(pCallback, punkState));
- ComPtr<IMFMediaEventQueue> spQueue;
+ return S_OK;
+ }
+ IFACEMETHODIMP SimpleMediaSource::EndGetEvent(
+ _In_ IMFAsyncResult* pResult,
+ _COM_Outptr_ IMFMediaEvent** ppEvent
+ )
{
- auto lock = _critSec.Lock();
+ winrt::slim_lock_guard lock(m_Lock);
+
+ RETURN_IF_FAILED(_CheckShutdownRequiresLock());
+ RETURN_IF_FAILED(m_spEventQueue->EndGetEvent(pResult, ppEvent));
- RETURN_IF_FAILED (_CheckShutdownRequiresLock());
- spQueue = _spEventQueue;
+ return S_OK;
}
- // Now get the event.
- RETURN_IF_FAILED (_spEventQueue->GetEvent(dwFlags, ppEvent));
+ IFACEMETHODIMP SimpleMediaSource::GetEvent(
+ DWORD dwFlags,
+ _COM_Outptr_ IMFMediaEvent** ppEvent
+ )
+ {
+ // NOTE:
+ // GetEvent can block indefinitely, so we don't hold the lock.
+ // This requires some juggling with the event queue pointer.
- return hr;
-}
+ wil::com_ptr_nothrow<IMFMediaEventQueue> spQueue;
-IFACEMETHODIMP
-SimpleMediaSource::QueueEvent(
- MediaEventType eventType,
- REFGUID guidExtendedType,
- HRESULT hrStatus,
- _In_opt_ PROPVARIANT const *pvValue
- )
-{
- HRESULT hr = S_OK;
- auto lock = _critSec.Lock();
+ {
+ winrt::slim_lock_guard lock(m_Lock);
- RETURN_IF_FAILED (_CheckShutdownRequiresLock());
- RETURN_IF_FAILED (_spEventQueue->QueueEventParamVar(eventType, guidExtendedType, hrStatus, pvValue));
+ RETURN_IF_FAILED(_CheckShutdownRequiresLock());
+ spQueue = m_spEventQueue;
+ }
- return hr;
-}
+ // Now get the event.
+ RETURN_IF_FAILED(spQueue->GetEvent(dwFlags, ppEvent));
-// IMFMediaSource methods
-IFACEMETHODIMP
-SimpleMediaSource::CreatePresentationDescriptor(
- _COM_Outptr_ IMFPresentationDescriptor **ppPresentationDescriptor
- )
-{
- HRESULT hr = S_OK;
- auto lock = _critSec.Lock();
+ return S_OK;
+ }
- if (ppPresentationDescriptor == nullptr)
+ IFACEMETHODIMP SimpleMediaSource::QueueEvent(
+ MediaEventType eventType,
+ REFGUID guidExtendedType,
+ HRESULT hrStatus,
+ _In_opt_ PROPVARIANT const* pvValue
+ )
{
- return E_POINTER;
- }
- *ppPresentationDescriptor = nullptr;
+ winrt::slim_lock_guard lock(m_Lock);
- RETURN_IF_FAILED (_CheckShutdownRequiresLock());
- RETURN_IF_FAILED (_spPresentationDescriptor->Clone(ppPresentationDescriptor));
+ RETURN_IF_FAILED(_CheckShutdownRequiresLock());
+ RETURN_IF_FAILED(m_spEventQueue->QueueEventParamVar(eventType, guidExtendedType, hrStatus, pvValue));
- return hr;
-}
-
-IFACEMETHODIMP
-SimpleMediaSource::GetCharacteristics(
- _Out_ DWORD *pdwCharacteristics
- )
-{
- HRESULT hr = S_OK;
- auto lock = _critSec.Lock();
+ return S_OK;
+ }
- if (nullptr == pdwCharacteristics)
+ // IMFMediaSource methods
+ IFACEMETHODIMP SimpleMediaSource::CreatePresentationDescriptor(
+ _COM_Outptr_ IMFPresentationDescriptor** ppPresentationDescriptor
+ )
{
- return E_POINTER;
- }
- *pdwCharacteristics = 0;
+ winrt::slim_lock_guard lock(m_Lock);
- RETURN_IF_FAILED (_CheckShutdownRequiresLock());
- *pdwCharacteristics = MFMEDIASOURCE_IS_LIVE;
+ RETURN_HR_IF_NULL(E_POINTER, ppPresentationDescriptor);
+ *ppPresentationDescriptor = nullptr;
- return hr;
-}
+ RETURN_IF_FAILED(_CheckShutdownRequiresLock());
+ RETURN_IF_FAILED(m_spPresentationDescriptor->Clone(ppPresentationDescriptor));
-IFACEMETHODIMP
-SimpleMediaSource::Pause(
- )
-{
- // Pause() not required/needed
- return MF_E_INVALID_STATE_TRANSITION;
-}
+ return S_OK;
+ }
+ IFACEMETHODIMP SimpleMediaSource::GetCharacteristics(
+ _Out_ DWORD* pdwCharacteristics
+ )
+ {
+ winrt::slim_lock_guard lock(m_Lock);
-IFACEMETHODIMP
-SimpleMediaSource::Shutdown(
- )
-{
- HRESULT hr = S_OK;
- auto lock = _critSec.Lock();
+ RETURN_HR_IF_NULL(E_POINTER, pdwCharacteristics);
+ *pdwCharacteristics = 0;
- _sourceState = SourceState::Shutdown;
+ RETURN_IF_FAILED(_CheckShutdownRequiresLock());
+ *pdwCharacteristics = MFMEDIASOURCE_IS_LIVE;
- _spAttributes.Reset();
- _spPresentationDescriptor.Reset();
+ return S_OK;
+ }
- if (_spEventQueue != nullptr)
+ IFACEMETHODIMP SimpleMediaSource::Pause()
{
- _spEventQueue->Shutdown();
- _spEventQueue.Reset();
+ // Pause() not required/needed
+ return MF_E_INVALID_STATE_TRANSITION;
}
- if (_stream != nullptr)
+
+ IFACEMETHODIMP SimpleMediaSource::Shutdown()
{
- _stream.Get()->Shutdown();
- _stream.Reset();
- }
+ winrt::slim_lock_guard lock(m_Lock);
- return hr;
-}
+ m_sourceState = SourceState::Shutdown;
-IFACEMETHODIMP
-SimpleMediaSource::Start(
- _In_ IMFPresentationDescriptor *pPresentationDescriptor,
- _In_opt_ const GUID *pguidTimeFormat,
- _In_ const PROPVARIANT *pvarStartPos
- )
-{
- HRESULT hr = S_OK;
- auto lock = _critSec.Lock();
- DWORD count = 0;
- PROPVARIANT startTime;
- BOOL selected = false;
- ComPtr<IMFStreamDescriptor> streamDesc;
- DWORD streamIndex = 0;
+ m_spAttributes.reset();
+ m_spPresentationDescriptor.reset();
- if (pPresentationDescriptor == nullptr || pvarStartPos == nullptr)
- {
- return E_INVALIDARG;
+ if (m_spEventQueue != nullptr)
+ {
+ m_spEventQueue->Shutdown();
+ m_spEventQueue.reset();
+ }
+
+ for(unsigned int i = 0; i < m_streamList.size(); i++)
+ {
+ m_streamList[i]->Shutdown();
+ }
+ m_streamList.reset();
+
+ return S_OK;
}
- else if (pguidTimeFormat != nullptr && *pguidTimeFormat != GUID_NULL)
+
+ IFACEMETHODIMP SimpleMediaSource::Start(
+ _In_ IMFPresentationDescriptor* pPresentationDescriptor,
+ _In_opt_ const GUID* pguidTimeFormat,
+ _In_ const PROPVARIANT* pvarStartPos
+ )
{
- return MF_E_UNSUPPORTED_TIME_FORMAT;
- }
+ winrt::slim_lock_guard lock(m_Lock);
+ DWORD count = 0;
+ wil::unique_prop_variant startTime;
- RETURN_IF_FAILED (_CheckShutdownRequiresLock());
+ if (pPresentationDescriptor == nullptr || pvarStartPos == nullptr)
+ {
+ return E_INVALIDARG;
+ }
- if (!(_sourceState != SourceState::Stopped || _sourceState != SourceState::Shutdown))
- {
- return MF_E_INVALID_STATE_TRANSITION;
- }
+ if (pguidTimeFormat != nullptr && *pguidTimeFormat != GUID_NULL)
+ {
+ return MF_E_UNSUPPORTED_TIME_FORMAT;
+ }
- _sourceState = SourceState::Started;
+ RETURN_IF_FAILED(_CheckShutdownRequiresLock());
- // 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));
+ if (!(m_sourceState != SourceState::Stopped || m_sourceState != SourceState::Shutdown))
+ {
+ return MF_E_INVALID_STATE_TRANSITION;
+ }
+ m_sourceState = SourceState::Started;
- // Send event that the source started. Include error code in case it failed.
- RETURN_IF_FAILED (_spEventQueue->QueueEventParamVar(MESourceStarted,
- GUID_NULL,
- hr,
- &startTime));
+ // 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));
- // 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;
- }
+ // 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.
+ for (unsigned int i = 0; i < count; i++)
+ {
+ BOOL selected = false;
+ wil::com_ptr_nothrow<IMFStreamDescriptor> streamDesc;
+ RETURN_IF_FAILED(pPresentationDescriptor->GetStreamDescriptorByIndex(
+ i,
+ &selected,
+ &streamDesc));
- if (selected)
- {
- ComPtr<IUnknown> spunkStream;
- MediaEventType met = (_wasStreamPreviouslySelected ? MEUpdatedStream : MENewStream);
+ DWORD streamId = 0;
+ RETURN_IF_FAILED(streamDesc->GetStreamIdentifier(&streamId));
- // 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));
+ DWORD streamIdx = 0;
+ bool wasSelected = false;
+ wil::com_ptr_nothrow<IMFStreamDescriptor> spLocalStreamDescriptor;
+ RETURN_IF_FAILED(_GetStreamDescriptorByStreamId(streamId, &streamIdx, &wasSelected, &spLocalStreamDescriptor));
+
+ if (selected)
+ {
+ // Update our internal PresentationDescriptor
+ RETURN_IF_FAILED(m_spPresentationDescriptor->SelectStream(streamIdx));
- // Send the MEUpdatedStream/MENewStream to our source event
- // queue.
- RETURN_IF_FAILED (_spEventQueue->QueueEventParamUnk(met,
- GUID_NULL,
- S_OK,
- spunkStream.Get()));
+ // Update stream state
+ RETURN_IF_FAILED(m_streamList[streamIdx]->SetStreamState(MF_STREAM_STATE_RUNNING));
+ RETURN_IF_FAILED(m_streamList[streamIdx]->Start());
- // 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;
+ // Send the MEUpdatedStream/MENewStream to our source event
+ // queue.
+ wil::com_ptr_nothrow<IUnknown> spunkStream;
+ MediaEventType met = (wasSelected ? MEUpdatedStream : MENewStream);
+ RETURN_IF_FAILED(m_streamList[streamIdx]->QueryInterface(IID_PPV_ARGS(&spunkStream)));
+ RETURN_IF_FAILED(m_spEventQueue->QueueEventParamUnk(
+ met,
+ GUID_NULL,
+ S_OK,
+ spunkStream.get()));
+ }
+ else if(wasSelected)
+ {
+ // stream was previously selected but not selected this time.
+ RETURN_IF_FAILED(m_spPresentationDescriptor->DeselectStream(streamIdx));
+ }
+ }
- return hr;
-}
+ // Send event that the source started. Include error code in case it failed.
+ RETURN_IF_FAILED(m_spEventQueue->QueueEventParamVar(
+ MESourceStarted,
+ GUID_NULL,
+ S_OK,
+ &startTime));
-IFACEMETHODIMP
-SimpleMediaSource::Stop(
- )
-{
- HRESULT hr = S_OK;
- auto lock = _critSec.Lock();
- PROPVARIANT stopTime;
- DWORD count = 0;
- MF_STREAM_STATE state;
+ return S_OK;
+ }
- if (_sourceState != SourceState::Started)
+ HRESULT SimpleMediaSource::_GetStreamDescriptorByStreamId(DWORD dwStreamId, DWORD* pdwStreamIdx, bool* pSelected, IMFStreamDescriptor** ppStreamDescriptor)
{
- return MF_E_INVALID_STATE_TRANSITION;
- }
+ RETURN_HR_IF_NULL(E_POINTER, ppStreamDescriptor);
+ *ppStreamDescriptor = nullptr;
+
+ RETURN_HR_IF_NULL(E_POINTER, pdwStreamIdx);
+ *pdwStreamIdx = 0;
- _sourceState = SourceState::Stopped;
+ RETURN_HR_IF_NULL(E_POINTER, pSelected);
+ *pSelected = false;
- RETURN_IF_FAILED (_CheckShutdownRequiresLock());
- RETURN_IF_FAILED (InitPropVariantFromInt64(MFGetSystemTime(), &stopTime));
- RETURN_IF_FAILED (_spPresentationDescriptor->GetStreamDescriptorCount(&count));
+ DWORD streamCount = 0;
+ RETURN_IF_FAILED(m_spPresentationDescriptor->GetStreamDescriptorCount(&streamCount));
+ for (unsigned int i = 0; i < streamCount; i++)
+ {
+ wil::com_ptr_nothrow<IMFStreamDescriptor> spStreamDescriptor;
+ BOOL selected = 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_IF_FAILED(m_spPresentationDescriptor->GetStreamDescriptorByIndex(i, &selected, &spStreamDescriptor));
- return hr;
-}
+ DWORD id = 0;
+ RETURN_IF_FAILED(spStreamDescriptor->GetStreamIdentifier(&id));
-// IMFMediaSourceEx
-IFACEMETHODIMP
-SimpleMediaSource::GetSourceAttributes(
- _COM_Outptr_ IMFAttributes** sourceAttributes
- )
-{
- HRESULT hr = S_OK;
- auto lock = _critSec.Lock();
+ if (dwStreamId == id)
+ {
+ // Found the streamDescriptor with matching streamId
+ *pdwStreamIdx = i;
+ *pSelected = !!selected;
+ RETURN_IF_FAILED(spStreamDescriptor.copy_to(ppStreamDescriptor));
+ return S_OK;
+ }
+ }
- if (nullptr == sourceAttributes)
- {
- return E_POINTER;
+ return MF_E_NOT_FOUND;
}
- RETURN_IF_FAILED (_CheckShutdownRequiresLock());
-
- *sourceAttributes = nullptr;
- if (_spAttributes.Get() == nullptr)
+ IFACEMETHODIMP SimpleMediaSource::Stop()
{
- ComPtr<IMFSensorProfileCollection> profileCollection;
- ComPtr<IMFSensorProfile> profile;
-
- // Create our source attribute store.
- RETURN_IF_FAILED (MFCreateAttributes(_spAttributes.GetAddressOf(), 1));
+ winrt::slim_lock_guard lock(m_Lock);
- // Create an empty profile collection...
- RETURN_IF_FAILED (MFCreateSensorProfileCollection(&profileCollection));
+ if (m_sourceState != SourceState::Started)
+ {
+ return MF_E_INVALID_STATE_TRANSITION;
+ }
+ m_sourceState = SourceState::Stopped;
- // In this example since we have just one stream, we only have one
- // pin to add: Pin0.
+ RETURN_IF_FAILED(_CheckShutdownRequiresLock());
- // 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()));
+ wil::unique_prop_variant stopTime;
+ RETURN_IF_FAILED(InitPropVariantFromInt64(MFGetSystemTime(), &stopTime));
- // 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()));
+ // Deselect the streams and send the stream stopped events.
+ for (unsigned int i = 0; i < m_streamList.size(); i++)
+ {
+ RETURN_IF_FAILED(m_streamList[i]->SetStreamState(MF_STREAM_STATE_STOPPED));
+ RETURN_IF_FAILED(m_streamList[i]->Stop());
+ RETURN_IF_FAILED(m_spPresentationDescriptor->DeselectStream(i));
+ }
+ RETURN_IF_FAILED(m_spEventQueue->QueueEventParamVar(MESourceStopped, GUID_NULL, S_OK, &stopTime));
- // Se the profile collection to the attribute store of the IMFTransform.
- RETURN_IF_FAILED (_spAttributes->SetUnknown(MF_DEVICEMFT_SENSORPROFILE_COLLECTION,
- profileCollection.Get()));
+ return S_OK;
}
- return _spAttributes.CopyTo(sourceAttributes);
-}
+ // IMFMediaSourceEx
+ IFACEMETHODIMP SimpleMediaSource::GetSourceAttributes(_COM_Outptr_ IMFAttributes** sourceAttributes)
+ {
+ winrt::slim_lock_guard lock(m_Lock);
+ RETURN_HR_IF_NULL(E_POINTER, sourceAttributes);
+ *sourceAttributes = nullptr;
-IFACEMETHODIMP
-SimpleMediaSource::GetStreamAttributes(
- DWORD dwStreamIdentifier,
- _COM_Outptr_ IMFAttributes **ppAttributes
- )
-{
- HRESULT hr = S_OK;
- auto lock = _critSec.Lock();
+ RETURN_IF_FAILED(_CheckShutdownRequiresLock());
- if (ppAttributes == nullptr)
- {
- return E_POINTER;
+ RETURN_IF_FAILED(MFCreateAttributes(sourceAttributes, 1));
+ RETURN_IF_FAILED(m_spAttributes->CopyAllItems(*sourceAttributes));
+
+ return S_OK;
}
- *ppAttributes = nullptr;
- RETURN_IF_FAILED (_CheckShutdownRequiresLock());
- if (dwStreamIdentifier >= NUM_STREAMS)
+ IFACEMETHODIMP SimpleMediaSource::GetStreamAttributes(
+ _In_ DWORD dwStreamIdentifier,
+ _COM_Outptr_ IMFAttributes** ppAttributes
+ )
{
- return MF_E_INVALIDSTREAMNUMBER;
+ winrt::slim_lock_guard lock(m_Lock);
+
+ RETURN_HR_IF_NULL(E_POINTER, ppAttributes);
+ *ppAttributes = nullptr;
+
+ RETURN_IF_FAILED(_CheckShutdownRequiresLock());
+
+ wil::com_ptr_nothrow<SimpleMediaStream> spStream;
+ RETURN_IF_FAILED(_GetMediaStreamById(dwStreamIdentifier, &spStream));
+ RETURN_IF_FAILED(spStream->m_spAttributes.copy_to(ppAttributes));
+
+ return S_OK;
}
- else
+
+ IFACEMETHODIMP SimpleMediaSource::SetD3DManager(
+ _In_opt_ IUnknown* /*pManager*/
+ )
{
- *ppAttributes = _stream.Get()->_spAttributes.Get();
- (*ppAttributes)->AddRef();
- }
+ // 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 hr;
-}
+ return E_NOTIMPL;
+ }
-IFACEMETHODIMP
-SimpleMediaSource::SetD3DManager(
- _In_opt_ IUnknown* /*pManager*/
- )
-{
- // 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.
+ // IMFGetService methods
+ _Use_decl_annotations_
+ IFACEMETHODIMP SimpleMediaSource::GetService(
+ _In_ REFGUID guidService,
+ _In_ REFIID riid,
+ _Out_ LPVOID* ppvObject
+ )
+ {
+ winrt::slim_lock_guard lock(m_Lock);
- return E_NOTIMPL;
-}
+ RETURN_IF_FAILED(_CheckShutdownRequiresLock());
-// IMFGetService methods
-_Use_decl_annotations_
-IFACEMETHODIMP
-SimpleMediaSource::GetService(
- _In_ REFGUID guidService,
- _In_ REFIID riid,
- _Out_ LPVOID * ppvObject
- )
-{
- HRESULT hr = S_OK;
- auto lock = _critSec.Lock();
+ RETURN_HR_IF_NULL(E_POINTER, ppvObject);
+ *ppvObject = nullptr;
- RETURN_IF_FAILED (_CheckShutdownRequiresLock());
+ // We have no supported service, just return
+ // MF_E_UNSUPPORTED_SERVICE for all calls.
+ return MF_E_UNSUPPORTED_SERVICE;
+ }
- if (!ppvObject)
+ // IKsControl methods
+ _Use_decl_annotations_
+ 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_POINTER;
- }
- *ppvObject = NULL;
+ if (ulPropertyLength < sizeof(KSPROPERTY))
+ {
+ return E_INVALIDARG;
+ }
+
+ // 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.
+ if ((pProperty->Set != PROPSETID_SIMPLEMEDIASOURCE_CUSTOMCONTROL) || (pProperty->Id >= KSPROPERTY_SIMPLEMEDIASOURCE_CUSTOMCONTROL_END))
+ {
+ return HRESULT_FROM_WIN32(ERROR_SET_NOT_FOUND);
+ }
- // We have no supported service, just return
- // MF_E_UNSUPPORTED_SERVICE for all calls.
- return MF_E_UNSUPPORTED_SERVICE;
-}
+ if (pPropertyData == NULL && ulDataLength == 0)
+ {
+ //
+ // If both PropertyData and DataLength, this function needs
+ // to return set BytesReturns to buffer size and
+ // return HRESULT_FROM_WIN32(ERROR_MORE_DATA)
+ // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ks/nf-ks-ikscontrol-ksproperty
+ //
+ RETURN_HR_IF_NULL(E_POINTER, pBytesReturned);
-// IKsControl methods
-_Use_decl_annotations_
-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
- )
-{
- // 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);
-}
+ switch (pProperty->Id)
+ {
+ case KSPROPERTY_SIMPLEMEDIASOURCE_CUSTOMCONTROL_COLORMODE:
+ *pBytesReturned = sizeof(KSPROPERTY_SIMPLEMEDIASOURCE_CUSTOMCONTROL_COLORMODE_S);
+ break;
-_Use_decl_annotations_
-IFACEMETHODIMP SimpleMediaSource::KsMethod(
- _In_reads_bytes_(ulMethodLength) PKSMETHOD pMethod,
- _In_ ULONG ulMethodLength,
- _Inout_updates_to_(ulDataLength, *pBytesReturned) LPVOID pMethodData,
- _In_ ULONG ulDataLength,
- _Out_ ULONG* pBytesReturned
- )
-{
- return HRESULT_FROM_WIN32(ERROR_SET_NOT_FOUND);
-}
+ default:
+ return HRESULT_FROM_WIN32(ERROR_SET_NOT_FOUND);
+ break;
+ }
+ return HRESULT_FROM_WIN32(ERROR_MORE_DATA);
+ }
+ else
+ {
+ RETURN_HR_IF_NULL(E_POINTER, pPropertyData);
+ RETURN_HR_IF(HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), ulDataLength == 0);
+ RETURN_HR_IF_NULL(E_POINTER, pBytesReturned);
-_Use_decl_annotations_
-IFACEMETHODIMP SimpleMediaSource::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
- )
-{
- return HRESULT_FROM_WIN32(ERROR_SET_NOT_FOUND);
-}
+ // validate properyData length
+ switch (pProperty->Id)
+ {
+ case KSPROPERTY_SIMPLEMEDIASOURCE_CUSTOMCONTROL_COLORMODE:
+ if (ulDataLength < sizeof(KSPROPERTY_SIMPLEMEDIASOURCE_CUSTOMCONTROL_COLORMODE_S))
+ {
+ return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+ }
-/// Internal methods.
-HRESULT
-SimpleMediaSource::_CheckShutdownRequiresLock(
- )
-{
- if (_sourceState == SourceState::Shutdown)
+ // Set operation
+ if (0 != (pProperty->Flags & (KSPROPERTY_TYPE_SET)))
+ {
+ DEBUG_MSG(L"Set filter level KSProperty");
+ *pBytesReturned = 0;
+ for (size_t i = 0; i < m_streamList.size(); i++)
+ {
+ m_streamList[i]->SetRGBMask(((PKSPROPERTY_SIMPLEMEDIASOURCE_CUSTOMCONTROL_COLORMODE_S)pPropertyData)->ColorMode);
+ *pBytesReturned = sizeof(KSPROPERTY_SIMPLEMEDIASOURCE_CUSTOMCONTROL_COLORMODE_S);
+ }
+ }
+ // Get operation
+ else if (0 != (pProperty->Flags & (KSPROPERTY_TYPE_GET)))
+ {
+ DEBUG_MSG(L"Get filter level KSProperty");
+ ((PKSPROPERTY_SIMPLEMEDIASOURCE_CUSTOMCONTROL_COLORMODE_S)pPropertyData)->ColorMode = m_streamList[0]->GetRGBMask();
+ *pBytesReturned = sizeof(KSPROPERTY_SIMPLEMEDIASOURCE_CUSTOMCONTROL_COLORMODE_S);
+ }
+ else
+ {
+ return E_INVALIDARG;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return S_OK;
+ }
+
+ _Use_decl_annotations_
+ IFACEMETHODIMP SimpleMediaSource::KsMethod(
+ _In_reads_bytes_(ulMethodLength) PKSMETHOD pMethod,
+ _In_ ULONG ulMethodLength,
+ _Inout_updates_to_(ulDataLength, *pBytesReturned) LPVOID pMethodData,
+ _In_ ULONG ulDataLength,
+ _Out_ ULONG* pBytesReturned
+ )
{
- return MF_E_SHUTDOWN;
+ return HRESULT_FROM_WIN32(ERROR_SET_NOT_FOUND);
}
- if (_spEventQueue == nullptr || _stream == nullptr)
+ _Use_decl_annotations_
+ IFACEMETHODIMP SimpleMediaSource::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
+ )
{
- return E_UNEXPECTED;
+ return HRESULT_FROM_WIN32(ERROR_SET_NOT_FOUND);
}
- return S_OK;
-}
+ IFACEMETHODIMP SimpleMediaSource::SetDefaultAllocator(
+ _In_ DWORD dwOutputStreamID,
+ _In_ IUnknown* pAllocator)
+ {
+ winrt::slim_lock_guard lock(m_Lock);
+ RETURN_IF_FAILED(_CheckShutdownRequiresLock());
-HRESULT
-SimpleMediaSource::_ValidatePresentationDescriptor(
- _In_ IMFPresentationDescriptor *pPD
- )
-{
- HRESULT hr = S_OK;
- DWORD cStreams = 0;
- bool anySelected = false;
+ wil::com_ptr_nothrow<IMFVideoSampleAllocator> spAllocator;
+ RETURN_IF_FAILED(pAllocator->QueryInterface(IID_PPV_ARGS(&spAllocator)));
+
+ wil::com_ptr_nothrow<SimpleMediaStream> spStream;
+ RETURN_IF_FAILED(_GetMediaStreamById(dwOutputStreamID, &spStream));
+ RETURN_IF_FAILED(spStream->SetSampleAllocator(spAllocator.get()));
- if (pPD == nullptr)
+ return S_OK;
+ }
+
+ IFACEMETHODIMP SimpleMediaSource::GetAllocatorUsage(
+ _In_ DWORD dwOutputStreamID,
+ _Out_ DWORD* pdwInputStreamID,
+ _Out_ MFSampleAllocatorUsage* peUsage)
{
- return E_INVALIDARG;
+ winrt::slim_lock_guard lock(m_Lock);
+ RETURN_IF_FAILED(_CheckShutdownRequiresLock());
+
+ RETURN_HR_IF_NULL(E_POINTER, pdwInputStreamID);
+ RETURN_HR_IF_NULL(E_POINTER, peUsage);
+
+ wil::com_ptr_nothrow<SimpleMediaStream> spStream;
+ RETURN_IF_FAILED(_GetMediaStreamById(dwOutputStreamID, &spStream));
+
+ *peUsage = spStream->SampleAlloactorUsage();
+ *pdwInputStreamID = dwOutputStreamID;
+
+ return S_OK;
}
- // The caller's PD must have the same number of streams as ours.
- RETURN_IF_FAILED (pPD->GetStreamDescriptorCount(&cStreams));
- if (SUCCEEDED(hr) && (cStreams != NUM_STREAMS))
+ /// Internal methods.
+ HRESULT SimpleMediaSource::_CheckShutdownRequiresLock()
{
- return E_INVALIDARG;
+ if (m_sourceState == SourceState::Shutdown)
+ {
+ return MF_E_SHUTDOWN;
+ }
+
+ if (m_spEventQueue == nullptr || m_streamList.get() == nullptr)
+ {
+ return E_UNEXPECTED;
+ }
+
+ return S_OK;
}
- // The caller must select at least one stream.
- for (UINT32 i = 0; i < cStreams; ++i)
+ HRESULT SimpleMediaSource::_ValidatePresentationDescriptor(_In_ IMFPresentationDescriptor* pPD)
{
- ComPtr<IMFStreamDescriptor> spSD;
- BOOL fSelected = FALSE;
- DWORD dwId = 0;
+ DWORD cStreams = 0;
+ bool anySelected = false;
+
+ RETURN_HR_IF_NULL(E_INVALIDARG, pPD);
+
+ // The caller's PD must have the same number of streams as ours.
+ RETURN_IF_FAILED(pPD->GetStreamDescriptorCount(&cStreams));
+ if (cStreams != m_streamList.size())
+ {
+ return E_INVALIDARG;
+ }
- RETURN_IF_FAILED (pPD->GetStreamDescriptorByIndex(i, &fSelected, &spSD));
+ // The caller must select at least one stream.
+ for (UINT32 i = 0; i < cStreams; ++i)
+ {
+ wil::com_ptr_nothrow<IMFStreamDescriptor> spSD;
+ BOOL fSelected = FALSE;
- anySelected |= !!fSelected;
+ RETURN_IF_FAILED(pPD->GetStreamDescriptorByIndex(i, &fSelected, &spSD));
+ anySelected |= !!fSelected;
+ }
- RETURN_IF_FAILED (spSD->GetStreamIdentifier(&dwId));
- if (dwId >= NUM_STREAMS)
+ if (!anySelected)
{
return E_INVALIDARG;
}
+
+ return S_OK;
}
- if (!anySelected)
+ HRESULT SimpleMediaSource::_CreateSourceAttributes()
{
- return E_INVALIDARG;
+ if (m_spAttributes.get() == nullptr)
+ {
+ // Create our source attribute store.
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spAttributes, 1));
+
+ wil::com_ptr_nothrow<IMFSensorProfileCollection> profileCollection;
+ wil::com_ptr_nothrow<IMFSensorProfile> profile;
+
+ // 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: Pin = STREAM_ID.
+
+ // Legacy profile is mandatory. This is to ensure non-profile
+ // aware applications can still function, but with degraded
+ // feature sets.
+ const DWORD STREAM_ID = 0;
+ RETURN_IF_FAILED(MFCreateSensorProfile(KSCAMERAPROFILE_Legacy, 0 /*ProfileIndex*/, nullptr,
+ &profile));
+ RETURN_IF_FAILED(profile->AddProfileFilter(STREAM_ID, 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 /*ProfileIndex*/, nullptr,
+ &profile));
+ RETURN_IF_FAILED(profile->AddProfileFilter(STREAM_ID, 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(m_spAttributes->SetUnknown(
+ MF_DEVICEMFT_SENSORPROFILE_COLLECTION,
+ profileCollection.get()));
+ }
+
+ return S_OK;
}
- return hr;
-}
+ HRESULT SimpleMediaSource::_GetMediaStreamById(_In_ DWORD dwStreamId, _COM_Outptr_ SimpleMediaStream** ppStream)
+ {
+ RETURN_HR_IF_NULL(E_POINTER, ppStream);
+ *ppStream = nullptr;
+ for (unsigned int i = 0; i < m_streamList.size(); i++)
+ {
+ if (m_streamList[i]->Id() == dwStreamId)
+ {
+ *ppStream = m_streamList[i];
+ (*ppStream)->AddRef();
+ return S_OK;
+ }
+ }
+ return MF_E_NOT_FOUND;
+ }
+}
diff --git a/general/SimpleMediaSource/MediaSource/SimpleMediaSource.h b/general/SimpleMediaSource/MediaSource/SimpleMediaSource.h
index 019926c8..10ac200b 100644
--- a/general/SimpleMediaSource/MediaSource/SimpleMediaSource.h
+++ b/general/SimpleMediaSource/MediaSource/SimpleMediaSource.h
@@ -1,81 +1,120 @@
+//
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
#pragma once
+#ifndef SIMPLEMEDIASOURCE_H
+#define SIMPLEMEDIASOURCE_H
-// Represents a simple media source that only has one stream and outputs a static image
+// Example Custom Property implemented by SimpleMediaSource
+//
+// {0CE2EF73-4800-4F53-9B8E-8C06790FC0C7}
+static const GUID PROPSETID_SIMPLEMEDIASOURCE_CUSTOMCONTROL =
+{ 0xce2ef73, 0x4800, 0x4f53, { 0x9b, 0x8e, 0x8c, 0x6, 0x79, 0xf, 0xc0, 0xc7 } };
-#include "stdafx.h"
+enum
+{
+ KSPROPERTY_SIMPLEMEDIASOURCE_CUSTOMCONTROL_COLORMODE = 0,
+ KSPROPERTY_SIMPLEMEDIASOURCE_CUSTOMCONTROL_END // all ids must define before this.
+};
-class SimpleMediaStream;
+#define KSPROPERTY_SIMPLEMEDIASOURCE_CUSTOMCONTROL_COLORMODE_GRAYSCALE 0x00FFFFFFL
+#define KSPROPERTY_SIMPLEMEDIASOURCE_CUSTOMCONTROL_COLORMODE_RED 0x00FF0000L
+#define KSPROPERTY_SIMPLEMEDIASOURCE_CUSTOMCONTROL_COLORMODE_GREEN 0x0000FF00L
+#define KSPROPERTY_SIMPLEMEDIASOURCE_CUSTOMCONTROL_COLORMODE_BLUE 0x000000FFL
-class __declspec(uuid("{9812588D-5CE9-4E4C-ABC1-049138D10DCE}"))
-SimpleMediaSource : public RuntimeClass<
- RuntimeClassFlags<WinRtClassicComMix>,
- IMFMediaEventGenerator,
- IMFMediaSource,
- IMFMediaSourceEx,
- IMFGetService,
- IKsControl>
-{
+typedef struct {
+ ULONG StremID;
+ ULONG ColorMode;
+} KSPROPERTY_SIMPLEMEDIASOURCE_CUSTOMCONTROL_COLORMODE_S, * PKSPROPERTY_SIMPLEMEDIASOURCE_CUSTOMCONTROL_COLORMODE_S;
- enum class SourceState
+namespace winrt::WindowsSample::implementation
+{
+ // forward declaration
+ struct SimpleMediaStream;
+
+ struct SimpleMediaSource : winrt::implements<SimpleMediaSource, IMFMediaSourceEx, IMFGetService, IKsControl, IMFSampleAllocatorControl>
{
- Invalid, Stopped, Started, Shutdown
- };
+ SimpleMediaSource() = default;
-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);
+ private:
+ enum class SourceState
+ {
+ Invalid, Stopped, Started, Shutdown
+ };
- // 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)();
+ public:
+ // IMFMediaEventGenerator (inherits by IMFMediaSource)
+ IFACEMETHODIMP BeginGetEvent(_In_ IMFAsyncCallback* pCallback, _In_ IUnknown* punkState) override;
+ IFACEMETHODIMP EndGetEvent(_In_ IMFAsyncResult* pResult, _Out_ IMFMediaEvent** ppEvent) override;
+ IFACEMETHODIMP GetEvent(DWORD dwFlags, _Out_ IMFMediaEvent** ppEvent) override;
+ IFACEMETHODIMP QueueEvent(MediaEventType met, REFGUID guidExtendedType, HRESULT hrStatus, _In_ const PROPVARIANT* pvValue) override;
- // IMFMediaSourceEx
- IFACEMETHOD(GetSourceAttributes)(_COM_Outptr_ IMFAttributes **ppAttributes);
- IFACEMETHOD(GetStreamAttributes)(DWORD dwStreamIdentifier, _COM_Outptr_ IMFAttributes **ppAttributes);
- IFACEMETHOD(SetD3DManager)(_In_opt_ IUnknown *pManager);
+ // IMFMediaSource (inherits by IMFMediaSourceEx)
+ IFACEMETHODIMP CreatePresentationDescriptor(_Out_ IMFPresentationDescriptor** ppPresentationDescriptor) override;
+ IFACEMETHODIMP GetCharacteristics(_Out_ DWORD* pdwCharacteristics) override;
+ IFACEMETHODIMP Pause() override;
+ IFACEMETHODIMP Shutdown() override;
+ IFACEMETHODIMP Start(_In_ IMFPresentationDescriptor* pPresentationDescriptor, _In_ const GUID* pguidTimeFormat, _In_ const PROPVARIANT* pvarStartPosition) override;
+ IFACEMETHODIMP Stop() override;
- // IMFGetService
- IFACEMETHOD(GetService)(_In_ REFGUID guidService, _In_ REFIID riid, _Out_ LPVOID *ppvObject);
+ // IMFMediaSourceEx
+ IFACEMETHODIMP GetSourceAttributes(_COM_Outptr_ IMFAttributes** ppAttributes) override;
+ IFACEMETHODIMP GetStreamAttributes(DWORD dwStreamIdentifier, _COM_Outptr_ IMFAttributes** ppAttributes) override;
+ IFACEMETHODIMP SetD3DManager(_In_opt_ IUnknown* pManager) override;
- // IKsControl
- 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();
+ // IMFGetService
+ IFACEMETHODIMP GetService(_In_ REFGUID guidService, _In_ REFIID riid, _Out_ LPVOID* ppvObject) override;
-private:
- HRESULT _CheckShutdownRequiresLock();
- HRESULT _ValidatePresentationDescriptor(_In_ IMFPresentationDescriptor *pPresentationDescriptor);
+ // IKsControl
+ IFACEMETHODIMP KsProperty(
+ _In_reads_bytes_(ulPropertyLength) PKSPROPERTY pProperty,
+ _In_ ULONG ulPropertyLength,
+ _Inout_updates_to_(ulDataLength, *pBytesReturned) LPVOID pPropertyData,
+ _In_ ULONG ulDataLength,
+ _Out_ ULONG* pBytesReturned) override;
+ IFACEMETHODIMP KsMethod(
+ _In_reads_bytes_(ulMethodLength) PKSMETHOD pMethod,
+ _In_ ULONG ulMethodLength,
+ _Inout_updates_to_(ulDataLength, *pBytesReturned) LPVOID pMethodData,
+ _In_ ULONG ulDataLength,
+ _Out_ ULONG* pBytesReturned) override;
+ IFACEMETHODIMP 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) override;
- CriticalSection _critSec;
- SourceState _sourceState{ SourceState::Invalid };
- ComPtr<IMFMediaEventQueue> _spEventQueue;
- ComPtr<IMFPresentationDescriptor> _spPresentationDescriptor;
- ComPtr<IMFAttributes> _spAttributes;
+ // IMFSampleAllocatorControl
+ IFACEMETHODIMP SetDefaultAllocator(
+ _In_ DWORD dwOutputStreamID,
+ _In_ IUnknown* pAllocator) override;
- bool _wasStreamPreviouslySelected; // maybe makes more sense as a property of the stream
- const DWORD NUM_STREAMS = 1;
- ComPtr<SimpleMediaStream> _stream;
-};
+ IFACEMETHODIMP GetAllocatorUsage(
+ _In_ DWORD dwOutputStreamID,
+ _Out_ DWORD* pdwInputStreamID,
+ _Out_ MFSampleAllocatorUsage* peUsage) override;
+
+ // Non-Interface functions
+ HRESULT Initialize();
+
+ private:
+ HRESULT _CheckShutdownRequiresLock();
+ HRESULT _ValidatePresentationDescriptor(_In_ IMFPresentationDescriptor* pPresentationDescriptor);
+ HRESULT _CreateSourceAttributes();
+ HRESULT _GetStreamDescriptorByStreamId(_In_ DWORD dwStreamId, _Out_ DWORD* pdwStreamIdx, _Out_ bool* pSelected, _COM_Outptr_ IMFStreamDescriptor** ppStreamDescriptor);
+ HRESULT _GetMediaStreamById(_In_ DWORD dwStreamId, _COM_Outptr_ SimpleMediaStream** ppMediaStream);
+
+ winrt::slim_mutex m_Lock;
+ SourceState m_sourceState{ SourceState::Invalid };
+
+ wil::com_ptr_nothrow<IMFMediaEventQueue> m_spEventQueue;
+ wil::com_ptr_nothrow<IMFPresentationDescriptor> m_spPresentationDescriptor;
+ wil::com_ptr_nothrow<IMFAttributes> m_spAttributes;
+ wil::unique_cotaskmem_array_ptr<wil::com_ptr_nothrow<SimpleMediaStream>> m_streamList;
+
+ const DWORD NUM_STREAMS = 1;
+ };
+}
-CoCreatableClass(SimpleMediaSource);
+#endif
diff --git a/general/SimpleMediaSource/MediaSource/SimpleMediaSourceActivate.cpp b/general/SimpleMediaSource/MediaSource/SimpleMediaSourceActivate.cpp
new file mode 100644
index 00000000..16abd28d
--- /dev/null
+++ b/general/SimpleMediaSource/MediaSource/SimpleMediaSourceActivate.cpp
@@ -0,0 +1,245 @@
+//
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+#include "pch.h"
+
+namespace winrt::WindowsSample::implementation
+{
+ // IMFActivate
+ IFACEMETHODIMP SimpleMediaSourceActivate::ActivateObject(REFIID riid, void** ppv)
+ {
+ RETURN_HR_IF_NULL(E_POINTER, ppv);
+ *ppv = nullptr;
+
+ wil::com_ptr_nothrow<IMFAttributes> spAttributes;
+ RETURN_IF_FAILED(MFCreateAttributes(&spAttributes, 1));
+
+ DEBUG_MSG(L"Activate SimpleMediaSource");
+ m_spSimpleMediaSrc = winrt::make_self<winrt::WindowsSample::implementation::SimpleMediaSource>();
+ RETURN_IF_FAILED(m_spSimpleMediaSrc->Initialize());
+ RETURN_IF_FAILED(m_spSimpleMediaSrc->QueryInterface(riid, ppv));
+
+ return S_OK;
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::ShutdownObject()
+ {
+ return S_OK;
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::DetachObject()
+ {
+ m_spSimpleMediaSrc = nullptr;
+ return S_OK;
+ }
+
+ // IMFAttributes (inherits by IMFActivate)
+ IFACEMETHODIMP SimpleMediaSourceActivate::GetItem(_In_ REFGUID guidKey, _Inout_opt_ PROPVARIANT* pValue)
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->GetItem(guidKey, pValue);
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::GetItemType(_In_ REFGUID guidKey, _Out_ MF_ATTRIBUTE_TYPE* pType)
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->GetItemType(guidKey, pType);
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::CompareItem(_In_ REFGUID guidKey, _In_ REFPROPVARIANT Value, _Out_ BOOL* pbResult)
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->CompareItem(guidKey, Value, pbResult);
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::Compare(_In_ IMFAttributes* pTheirs, _In_ MF_ATTRIBUTES_MATCH_TYPE MatchType, _Out_ BOOL* pbResult)
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->Compare(pTheirs, MatchType, pbResult);
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::GetUINT32(_In_ REFGUID guidKey, _Out_ UINT32* punValue)
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->GetUINT32(guidKey, punValue);
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::GetUINT64(_In_ REFGUID guidKey, _Out_ UINT64* punValue)
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->GetUINT64(guidKey, punValue);
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::GetDouble(_In_ REFGUID guidKey, _Out_ double* pfValue)
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->GetDouble(guidKey, pfValue);
+ }
+ IFACEMETHODIMP SimpleMediaSourceActivate::GetGUID(_In_ REFGUID guidKey, _Out_ GUID* pguidValue)
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->GetGUID(guidKey, pguidValue);
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::GetStringLength(_In_ REFGUID guidKey, _Out_ UINT32* pcchLength)
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->GetStringLength(guidKey, pcchLength);
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::GetString(_In_ REFGUID guidKey, _Out_writes_(cchBufSize) LPWSTR pwszValue, _In_ UINT32 cchBufSize, _Inout_opt_ UINT32* pcchLength)
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->GetString(guidKey, pwszValue, cchBufSize, pcchLength);
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::GetAllocatedString(_In_ REFGUID guidKey, _Out_writes_(*pcchLength + 1) LPWSTR* ppwszValue, _Inout_ UINT32* pcchLength)
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->GetAllocatedString(guidKey, ppwszValue, pcchLength);
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::GetBlobSize(_In_ REFGUID guidKey, _Out_ UINT32* pcbBlobSize)
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->GetBlobSize(guidKey, pcbBlobSize);
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::GetBlob(_In_ REFGUID guidKey, _Out_writes_(cbBufSize) UINT8* pBuf, UINT32 cbBufSize, _Inout_ UINT32* pcbBlobSize)
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->GetBlob(guidKey, pBuf, cbBufSize, pcbBlobSize);
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::GetAllocatedBlob(__RPC__in REFGUID guidKey, __RPC__deref_out_ecount_full_opt(*pcbSize) UINT8** ppBuf, __RPC__out UINT32* pcbSize)
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->GetAllocatedBlob(guidKey, ppBuf, pcbSize);
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::GetUnknown(__RPC__in REFGUID guidKey, __RPC__in REFIID riid, __RPC__deref_out_opt LPVOID* ppv)
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->GetUnknown(guidKey, riid, ppv);
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::SetItem(_In_ REFGUID guidKey, _In_ REFPROPVARIANT Value)
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->SetItem(guidKey, Value);
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::DeleteItem(_In_ REFGUID guidKey)
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->DeleteItem(guidKey);
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::DeleteAllItems()
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->DeleteAllItems();
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::SetUINT32(_In_ REFGUID guidKey, _In_ UINT32 unValue)
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->SetUINT32(guidKey, unValue);
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::SetUINT64(_In_ REFGUID guidKey, _In_ UINT64 unValue)
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->SetUINT64(guidKey, unValue);
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::SetDouble(_In_ REFGUID guidKey, _In_ double fValue)
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->SetDouble(guidKey, fValue);
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::SetGUID(_In_ REFGUID guidKey, _In_ REFGUID guidValue)
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->SetGUID(guidKey, guidValue);
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::SetString(_In_ REFGUID guidKey, _In_ LPCWSTR wszValue)
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->SetString(guidKey, wszValue);
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::SetBlob(_In_ REFGUID guidKey, _In_reads_(cbBufSize) const UINT8* pBuf, UINT32 cbBufSize)
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->SetBlob(guidKey, pBuf, cbBufSize);
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::SetUnknown(_In_ REFGUID guidKey, _In_ IUnknown* pUnknown)
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->SetUnknown(guidKey, pUnknown);
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::LockStore()
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->LockStore();
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::UnlockStore()
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->UnlockStore();
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::GetCount(_Out_ UINT32* pcItems)
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->GetCount(pcItems);
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::GetItemByIndex(UINT32 unIndex, _Out_ GUID* pguidKey, _Inout_ PROPVARIANT* pValue)
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->GetItemByIndex(unIndex, pguidKey, pValue);
+ }
+
+ IFACEMETHODIMP SimpleMediaSourceActivate::CopyAllItems(_In_ IMFAttributes* pDest)
+ {
+ if (!m_spActivateAttributes)
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spActivateAttributes, 1));
+ return m_spActivateAttributes->CopyAllItems(pDest);
+ }
+}
diff --git a/general/SimpleMediaSource/MediaSource/SimpleMediaSourceActivate.h b/general/SimpleMediaSource/MediaSource/SimpleMediaSourceActivate.h
new file mode 100644
index 00000000..f206e6d9
--- /dev/null
+++ b/general/SimpleMediaSource/MediaSource/SimpleMediaSourceActivate.h
@@ -0,0 +1,82 @@
+//
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+#pragma once
+#ifndef SIMPLEMEDIASOURCEACTIVATE_H
+#define SIMPLEMEDIASOURCEACTIVATE_H
+
+namespace winrt::WindowsSample::implementation
+{
+ struct __declspec(uuid("9812588D-5CE9-4E4C-ABC1-049138D10DCE"))
+ SimpleMediaSourceActivate : winrt::implements<SimpleMediaSourceActivate, IMFActivate>
+ {
+ SimpleMediaSourceActivate() = default;
+
+ public:
+ // IMFActivate
+ IFACEMETHODIMP ActivateObject(REFIID riid, void** ppv) override;
+ IFACEMETHODIMP ShutdownObject() override;
+ IFACEMETHODIMP DetachObject() override;
+
+ // IMFAttributes (inherits by IMFActivate)
+ IFACEMETHODIMP GetItem(_In_ REFGUID guidKey, _Inout_opt_ PROPVARIANT* pValue) override;
+ IFACEMETHODIMP GetItemType(_In_ REFGUID guidKey, _Out_ MF_ATTRIBUTE_TYPE* pType) override;
+ IFACEMETHODIMP CompareItem(_In_ REFGUID guidKey, _In_ REFPROPVARIANT Value, _Out_ BOOL* pbResult) override;
+ IFACEMETHODIMP Compare(_In_ IMFAttributes* pTheirs, _In_ MF_ATTRIBUTES_MATCH_TYPE MatchType, _Out_ BOOL* pbResult) override;
+ IFACEMETHODIMP GetUINT32(_In_ REFGUID guidKey, _Out_ UINT32* punValue) override;
+ IFACEMETHODIMP GetUINT64(_In_ REFGUID guidKey, _Out_ UINT64* punValue) override;
+ IFACEMETHODIMP GetDouble(_In_ REFGUID guidKey, _Out_ double* pfValue) override;
+ IFACEMETHODIMP GetGUID(_In_ REFGUID guidKey, _Out_ GUID* pguidValue) override;
+ IFACEMETHODIMP GetStringLength(_In_ REFGUID guidKey, _Out_ UINT32* pcchLength) override;
+ IFACEMETHODIMP GetString(_In_ REFGUID guidKey, _Out_writes_(cchBufSize) LPWSTR pwszValue, _In_ UINT32 cchBufSize, _Inout_opt_ UINT32* pcchLength) override;
+ IFACEMETHODIMP GetAllocatedString(_In_ REFGUID guidKey, _Out_writes_(*pcchLength + 1) LPWSTR* ppwszValue, _Inout_ UINT32* pcchLength) override;
+ IFACEMETHODIMP GetBlobSize(_In_ REFGUID guidKey, _Out_ UINT32* pcbBlobSize) override;
+ IFACEMETHODIMP GetBlob(_In_ REFGUID guidKey, _Out_writes_(cbBufSize) UINT8* pBuf, UINT32 cbBufSize, _Inout_ UINT32* pcbBlobSize) override;
+ IFACEMETHODIMP GetAllocatedBlob(__RPC__in REFGUID guidKey, __RPC__deref_out_ecount_full_opt(*pcbSize) UINT8** ppBuf, __RPC__out UINT32* pcbSize) override;
+ IFACEMETHODIMP GetUnknown(__RPC__in REFGUID guidKey, __RPC__in REFIID riid, __RPC__deref_out_opt LPVOID* ppv) override;
+ IFACEMETHODIMP SetItem(_In_ REFGUID guidKey, _In_ REFPROPVARIANT Value) override;
+ IFACEMETHODIMP DeleteItem(_In_ REFGUID guidKey) override;
+ IFACEMETHODIMP DeleteAllItems() override;
+ IFACEMETHODIMP SetUINT32(_In_ REFGUID guidKey, _In_ UINT32 unValue) override;
+ IFACEMETHODIMP SetUINT64(_In_ REFGUID guidKey, _In_ UINT64 unValue) override;
+ IFACEMETHODIMP SetDouble(_In_ REFGUID guidKey, _In_ double fValue) override;
+ IFACEMETHODIMP SetGUID(_In_ REFGUID guidKey, _In_ REFGUID guidValue) override;
+ IFACEMETHODIMP SetString(_In_ REFGUID guidKey, _In_ LPCWSTR wszValue) override;
+ IFACEMETHODIMP SetBlob(_In_ REFGUID guidKey, _In_reads_(cbBufSize) const UINT8* pBuf, UINT32 cbBufSize) override;
+ IFACEMETHODIMP SetUnknown(_In_ REFGUID guidKey, _In_ IUnknown* pUnknown) override;
+ IFACEMETHODIMP LockStore() override;
+ IFACEMETHODIMP UnlockStore() override;
+ IFACEMETHODIMP GetCount(_Out_ UINT32* pcItems) override;
+ IFACEMETHODIMP GetItemByIndex(UINT32 unIndex, _Out_ GUID* pguidKey, _Inout_ PROPVARIANT* pValue) override;
+ IFACEMETHODIMP CopyAllItems(_In_ IMFAttributes* pDest) override;
+
+ private:
+ wil::com_ptr_nothrow <IMFAttributes> m_spActivateAttributes;
+ winrt::com_ptr<winrt::WindowsSample::implementation::SimpleMediaSource> m_spSimpleMediaSrc;
+ };
+}
+
+//
+// cocreatable class
+//
+struct SimpleMediaSourceActivateFactory : public winrt::implements<SimpleMediaSourceActivateFactory, IClassFactory>
+{
+public:
+ STDMETHODIMP CreateInstance(_In_ IUnknown*, _In_ REFIID riid, _COM_Outptr_ void** result) noexcept final try
+ {
+ RETURN_HR_IF_NULL(E_POINTER, result);
+ *result = nullptr;
+
+ winrt::com_ptr<winrt::WindowsSample::implementation::SimpleMediaSourceActivate> ptr = winrt::make_self<winrt::WindowsSample::implementation::SimpleMediaSourceActivate>();
+ return ptr->QueryInterface(riid, result);
+ } CATCH_RETURN()
+
+
+ STDMETHODIMP LockServer(BOOL) noexcept final
+ {
+ return S_OK;
+ }
+};
+
+
+#endif
diff --git a/general/SimpleMediaSource/MediaSource/SimpleMediaStream.cpp b/general/SimpleMediaSource/MediaSource/SimpleMediaStream.cpp
index 7685b12e..c22d7421 100644
--- a/general/SimpleMediaSource/MediaSource/SimpleMediaStream.cpp
+++ b/general/SimpleMediaSource/MediaSource/SimpleMediaStream.cpp
@@ -1,391 +1,403 @@
-#include "stdafx.h"
+//
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
-#define NUM_IMAGE_ROWS 240
-#define NUM_IMAGE_COLS 320
+#include "pch.h"
+
+#define NUM_IMAGE_ROWS 480
+#define NUM_IMAGE_COLS 640
#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)
-HRESULT
-SimpleMediaStream::RuntimeClassInitialize(
- _In_ SimpleMediaSource *pSource
- )
+namespace winrt::WindowsSample::implementation
{
- HRESULT hr = S_OK;
- ComPtr<IMFMediaTypeHandler> spTypeHandler;
- ComPtr<IMFAttributes> attrs;
-
- if (nullptr == pSource)
+ HRESULT SimpleMediaStream::Initialize(
+ _In_ SimpleMediaSource* pSource,
+ _In_ DWORD dwStreamId,
+ _In_ MFSampleAllocatorUsage allocatorUsage
+ )
{
- return E_INVALIDARG;
- }
- RETURN_IF_FAILED (pSource->QueryInterface(IID_PPV_ARGS(&_parent)));
+ wil::com_ptr_nothrow<IMFMediaTypeHandler> spTypeHandler;
+ wil::com_ptr_nothrow<IMFAttributes> attrs;
- // Initialize media type and set the video output media type.
- 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);
- _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);
+ RETURN_HR_IF_NULL(E_INVALIDARG, pSource);
+ m_parent = pSource;
- RETURN_IF_FAILED (MFCreateAttributes(&_spAttributes, 10));
- RETURN_IF_FAILED (this->_SetStreamAttributes(_spAttributes.Get()));
- RETURN_IF_FAILED (MFCreateEventQueue(&_spEventQueue));
+ m_dwStreamId = dwStreamId;
+ m_allocatorUsage = allocatorUsage;
- // Initialize stream descriptors
- RETURN_IF_FAILED (MFCreateStreamDescriptor(0, 1, _spMediaType.GetAddressOf(), &_spStreamDesc));
+ const uint32_t NUM_MEDIATYPES = 2;
+ wil::unique_cotaskmem_array_ptr<wil::com_ptr_nothrow<IMFMediaType>> mediaTypeList = wilEx::make_unique_cotaskmem_array<wil::com_ptr_nothrow<IMFMediaType>>(NUM_MEDIATYPES);
- RETURN_IF_FAILED (_spStreamDesc->GetMediaTypeHandler(&spTypeHandler));
- RETURN_IF_FAILED (spTypeHandler->SetCurrentMediaType(_spMediaType.Get()));
- RETURN_IF_FAILED (this->_SetStreamDescriptorAttributes(_spStreamDesc.Get()));
-
- return hr;
-}
+ // Initialize media type and set the video output media type.
+ wil::com_ptr_nothrow<IMFMediaType> spMediaType;
+ RETURN_IF_FAILED(MFCreateMediaType(&spMediaType));
+ spMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
+ spMediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_NV12);
+ 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);
+ // frame size * pixle bit size * framerate
+ uint32_t bitrate = (uint32_t)(NUM_IMAGE_COLS * 1.5 * NUM_IMAGE_ROWS * 8* 30);
+ spMediaType->SetUINT32(MF_MT_AVG_BITRATE, bitrate);
+ MFSetAttributeRatio(spMediaType.get(), MF_MT_PIXEL_ASPECT_RATIO, 1, 1);
+ mediaTypeList[0] = spMediaType.detach();
-// IMFMediaEventGenerator
-IFACEMETHODIMP
-SimpleMediaStream::BeginGetEvent(
- _In_ IMFAsyncCallback *pCallback,
- _In_ IUnknown *punkState
- )
-{
- HRESULT hr = S_OK;
- auto lock = _critSec.Lock();
+ 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);
+ 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);
+ // frame size * pixle bit size * framerate
+ bitrate = NUM_IMAGE_COLS * NUM_IMAGE_ROWS * 4 * 8* 30;
+ spMediaType->SetUINT32(MF_MT_AVG_BITRATE, bitrate);
+ MFSetAttributeRatio(spMediaType.get(), MF_MT_PIXEL_ASPECT_RATIO, 1, 1);
+ mediaTypeList[1] = spMediaType.detach();
- RETURN_IF_FAILED (_CheckShutdownRequiresLock());
- RETURN_IF_FAILED (_spEventQueue->BeginGetEvent(pCallback, punkState));
+ RETURN_IF_FAILED(MFCreateAttributes(&m_spAttributes, 10));
+ RETURN_IF_FAILED(_SetStreamAttributes(m_spAttributes.get()));
- return hr;
-}
+ RETURN_IF_FAILED(MFCreateEventQueue(&m_spEventQueue));
-IFACEMETHODIMP
-SimpleMediaStream::EndGetEvent(
- _In_ IMFAsyncResult *pResult,
- _COM_Outptr_ IMFMediaEvent **ppEvent
- )
-{
- HRESULT hr = S_OK;
- auto lock = _critSec.Lock();
+ // Initialize stream descriptors
+ RETURN_IF_FAILED(MFCreateStreamDescriptor(m_dwStreamId /*StreamId*/, NUM_MEDIATYPES /*MT count*/, mediaTypeList.get(), &m_spStreamDesc));
- RETURN_IF_FAILED (_CheckShutdownRequiresLock());
- RETURN_IF_FAILED (_spEventQueue->EndGetEvent(pResult, ppEvent));
+ RETURN_IF_FAILED(m_spStreamDesc->GetMediaTypeHandler(&spTypeHandler));
+ RETURN_IF_FAILED(spTypeHandler->SetCurrentMediaType(mediaTypeList[0]));
+ RETURN_IF_FAILED(_SetStreamDescriptorAttributes(m_spStreamDesc.get()));
- return hr;
-}
+ return S_OK;
+ }
-IFACEMETHODIMP
-SimpleMediaStream::GetEvent(
- DWORD dwFlags,
- _COM_Outptr_ IMFMediaEvent **ppEvent
- )
-{
- // NOTE:
- // GetEvent can block indefinitely, so we don't hold the lock.
- // This requires some juggling with the event queue pointer.
+ // IMFMediaEventGenerator
+ IFACEMETHODIMP SimpleMediaStream::BeginGetEvent(
+ _In_ IMFAsyncCallback* pCallback,
+ _In_ IUnknown* punkState
+ )
+ {
+ winrt::slim_lock_guard lock(m_Lock);
- HRESULT hr = S_OK;
+ RETURN_IF_FAILED(_CheckShutdownRequiresLock());
+ RETURN_IF_FAILED(m_spEventQueue->BeginGetEvent(pCallback, punkState));
- ComPtr<IMFMediaEventQueue> spQueue;
+ return S_OK;
+ }
+ IFACEMETHODIMP SimpleMediaStream::EndGetEvent(
+ _In_ IMFAsyncResult* pResult,
+ _COM_Outptr_ IMFMediaEvent** ppEvent
+ )
{
- auto lock = _critSec.Lock();
+ winrt::slim_lock_guard lock(m_Lock);
- RETURN_IF_FAILED (_CheckShutdownRequiresLock());
- spQueue = _spEventQueue;
+ RETURN_IF_FAILED(_CheckShutdownRequiresLock());
+ RETURN_IF_FAILED(m_spEventQueue->EndGetEvent(pResult, ppEvent));
+
+ return S_OK;
}
- // Now get the event.
- RETURN_IF_FAILED (_spEventQueue->GetEvent(dwFlags, ppEvent));
+ IFACEMETHODIMP SimpleMediaStream::GetEvent(
+ _In_ DWORD dwFlags,
+ _COM_Outptr_ IMFMediaEvent** ppEvent
+ )
+ {
+ // NOTE:
+ // GetEvent can block indefinitely, so we don't hold the lock.
+ // This requires some juggling with the event queue pointer.
- return hr;
-}
+ wil::com_ptr_nothrow<IMFMediaEventQueue> spQueue;
-IFACEMETHODIMP
-SimpleMediaStream::QueueEvent(
- MediaEventType eventType,
- REFGUID guidExtendedType,
- HRESULT hrStatus,
- _In_opt_ PROPVARIANT const *pvValue
- )
-{
- HRESULT hr = S_OK;
- auto lock = _critSec.Lock();
+ {
+ winrt::slim_lock_guard lock(m_Lock);
- RETURN_IF_FAILED (_CheckShutdownRequiresLock());
- RETURN_IF_FAILED (_spEventQueue->QueueEventParamVar(eventType, guidExtendedType, hrStatus, pvValue));
+ RETURN_IF_FAILED(_CheckShutdownRequiresLock());
+ spQueue = m_spEventQueue;
+ }
- return hr;
-}
+ // Now get the event.
+ RETURN_IF_FAILED(spQueue->GetEvent(dwFlags, ppEvent));
-// IMFMediaStream
-IFACEMETHODIMP
-SimpleMediaStream::GetMediaSource(
- _COM_Outptr_ IMFMediaSource **ppMediaSource
- )
-{
- HRESULT hr = S_OK;
- auto lock = _critSec.Lock();
+ return S_OK;
+ }
- if (ppMediaSource == nullptr)
+ IFACEMETHODIMP SimpleMediaStream::QueueEvent(
+ _In_ MediaEventType eventType,
+ _In_ REFGUID guidExtendedType,
+ _In_ HRESULT hrStatus,
+ _In_opt_ PROPVARIANT const* pvValue
+ )
{
- return E_POINTER;
+ winrt::slim_lock_guard lock(m_Lock);
+
+ RETURN_IF_FAILED(_CheckShutdownRequiresLock());
+ RETURN_IF_FAILED(m_spEventQueue->QueueEventParamVar(eventType, guidExtendedType, hrStatus, pvValue));
+
+ return S_OK;
}
- *ppMediaSource = nullptr;
- RETURN_IF_FAILED (_CheckShutdownRequiresLock());
+ // IMFMediaStream
+ IFACEMETHODIMP SimpleMediaStream::GetMediaSource(
+ _COM_Outptr_ IMFMediaSource** ppMediaSource
+ )
+ {
+ winrt::slim_lock_guard lock(m_Lock);
- *ppMediaSource = _parent.Get();
- (*ppMediaSource)->AddRef();
+ RETURN_HR_IF_NULL(E_POINTER, ppMediaSource);
+ *ppMediaSource = nullptr;
- return hr;
-}
+ RETURN_IF_FAILED(_CheckShutdownRequiresLock());
+ RETURN_IF_FAILED(m_parent.copy_to(ppMediaSource));
-IFACEMETHODIMP
-SimpleMediaStream::GetStreamDescriptor(
- _COM_Outptr_ IMFStreamDescriptor **ppStreamDescriptor
- )
-{
- HRESULT hr = S_OK;
- auto lock = _critSec.Lock();
+ return S_OK;
+ }
- if (ppStreamDescriptor == nullptr)
+ IFACEMETHODIMP SimpleMediaStream::GetStreamDescriptor(
+ _COM_Outptr_ IMFStreamDescriptor** ppStreamDescriptor
+ )
{
- return E_POINTER;
- }
- *ppStreamDescriptor = nullptr;
+ winrt::slim_lock_guard lock(m_Lock);
- RETURN_IF_FAILED (_CheckShutdownRequiresLock());
+ RETURN_HR_IF_NULL(E_POINTER, ppStreamDescriptor);
+ *ppStreamDescriptor = nullptr;
- if (_spStreamDesc != nullptr)
- {
- *ppStreamDescriptor = _spStreamDesc.Get();
- (*ppStreamDescriptor)->AddRef();
+ RETURN_IF_FAILED(_CheckShutdownRequiresLock());
+
+ if (m_spStreamDesc != nullptr)
+ {
+ RETURN_IF_FAILED(m_spStreamDesc.copy_to(ppStreamDescriptor));
+ }
+ else
+ {
+ return E_UNEXPECTED;
+ }
+
+ return S_OK;
}
- else
+
+ IFACEMETHODIMP SimpleMediaStream::RequestSample(
+ _In_ IUnknown* pToken
+ )
{
- return E_UNEXPECTED;
- }
+ winrt::slim_lock_guard lock(m_Lock);
+ wil::com_ptr_nothrow<IMFSample> sample;
+ wil::com_ptr_nothrow<IMFMediaBuffer> outputBuffer;
+ LONG pitch = 0;
+ BYTE* bufferStart = nullptr; // not used
+ DWORD bufferLength = 0;
+ BYTE* pbuf = nullptr;
+ wil::com_ptr_nothrow<IMF2DBuffer2> buffer2D;
- return hr;
-}
+ RETURN_IF_FAILED(_CheckShutdownRequiresLock());
-/*
- Writes to a buffer representing a 2D image.
- Writes a different constant to each line based on row number and current time.
+ if (m_streamState != MF_STREAM_STATE_RUNNING)
+ {
+ RETURN_HR_MSG(MF_E_INVALIDREQUEST, "Stream is not in running state, state:%d", m_streamState);
+ }
- Assumes top down image, no negative stride and pBuf points to the begnning of the buffer of length len.
+ RETURN_IF_FAILED(m_spSampleAllocator->AllocateSample(&sample));
+ RETURN_IF_FAILED(sample->GetBufferByIndex(0, &outputBuffer));
+ RETURN_IF_FAILED(outputBuffer->QueryInterface(IID_PPV_ARGS(&buffer2D)));
+ RETURN_IF_FAILED(buffer2D->Lock2DSize(MF2DBuffer_LockFlags_Write,
+ &pbuf,
+ &pitch,
+ &bufferStart,
+ &bufferLength));
+
- Param:
- pBuf - pointer to beginning of buffer
- pitch - line length in bytes
- len - length of buffer in bytes
-*/
-HRESULT
-WriteSampleData(
- _Inout_updates_bytes_(len) BYTE *pBuf,
- _In_ LONG pitch,
- _In_ DWORD len
- )
-{
- if (pBuf == nullptr)
- {
- return E_INVALIDARG;
- }
+ RETURN_IF_FAILED(m_spFrameGenerator->CreateFrame(pbuf, bufferLength, pitch, m_rgbMask));
+ RETURN_IF_FAILED(buffer2D->Unlock2D());
- const int NUM_ROWS = len / abs(pitch);
+ RETURN_IF_FAILED(sample->SetSampleTime(MFGetSystemTime()));
+ RETURN_IF_FAILED(sample->SetSampleDuration(333333));
+ if (pToken != nullptr)
+ {
+ RETURN_IF_FAILED(sample->SetUnknown(MFSampleExtension_Token, pToken));
+ }
+ RETURN_IF_FAILED(m_spEventQueue->QueueEventParamUnk(MEMediaSample,
+ GUID_NULL,
+ S_OK,
+ sample.get()));
- LONGLONG curSysTimeInS = MFGetSystemTime() / (MFTIME)10000000;
- int offset = curSysTimeInS % NUM_ROWS;
+ return S_OK;
+ }
- for (int r = 0; r < NUM_ROWS; r++)
+ //////////////////////////////////////////////////////////////////////////////////////////
+ // IMFMediaStream2
+ IFACEMETHODIMP SimpleMediaStream::SetStreamState(MF_STREAM_STATE state)
{
- int grayColor = r + offset;
- memset(pBuf + (pitch * r), (BYTE)(grayColor % NUM_ROWS), pitch);
- }
+ winrt::slim_lock_guard lock(m_Lock);
+ RETURN_IF_FAILED(_CheckShutdownRequiresLock());
- return S_OK;
-}
+ switch (state)
+ {
+ case MF_STREAM_STATE_PAUSED:
+ // because not supported
+ break;
-IFACEMETHODIMP
-SimpleMediaStream::RequestSample(
- _In_ IUnknown *pToken
- )
-{
- HRESULT hr = S_OK;
- auto lock = _critSec.Lock();
- ComPtr<IMFSample> sample;
- ComPtr<IMFMediaBuffer> outputBuffer;
- LONG pitch = IMAGE_ROW_SIZE_BYTES;
- BYTE *bufferStart = nullptr; // not used
- DWORD bufferLength = 0;
- BYTE *pbuf = nullptr;
- ComPtr<IMF2DBuffer2> buffer2D;
+ case MF_STREAM_STATE_RUNNING:
+ m_streamState = state;
+ break;
- 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)
- {
- RETURN_IF_FAILED (sample->SetUnknown(MFSampleExtension_Token, pToken));
- }
- RETURN_IF_FAILED (_spEventQueue->QueueEventParamUnk(MEMediaSample,
- GUID_NULL,
- S_OK,
- sample.Get()));
+ case MF_STREAM_STATE_STOPPED:
+ m_streamState = state;
- return hr;
-}
+ break;
-//////////////////////////////////////////////////////////////////////////////////////////
-// IMFMediaStream2
-IFACEMETHODIMP
-SimpleMediaStream::SetStreamState(
- MF_STREAM_STATE state
- )
-{
- HRESULT hr = S_OK;
- auto lock = _critSec.Lock();
- bool runningState = false;
+ default:
+ return MF_E_INVALID_STATE_TRANSITION;
+ break;
+ }
- RETURN_IF_FAILED (_CheckShutdownRequiresLock());
+ return S_OK;
+ }
- switch (state)
+ IFACEMETHODIMP SimpleMediaStream::GetStreamState(
+ _Out_ MF_STREAM_STATE* pState
+ )
{
- 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;
- }
+ winrt::slim_lock_guard lock(m_Lock);
+ RETURN_IF_FAILED(_CheckShutdownRequiresLock());
- _isSelected = runningState;
+ *pState = m_streamState;
-done:
- return hr;
-}
+ return S_OK;
+ }
-IFACEMETHODIMP
-SimpleMediaStream::GetStreamState(
- _Out_ MF_STREAM_STATE *pState
- )
-{
- HRESULT hr = S_OK;
- auto lock = _critSec.Lock();
- BOOLEAN pauseState = false;
+ //////////////////////////////////////////////////////////////////////////////////////////
+ // Public methods
+ HRESULT SimpleMediaStream::Start()
+ {
+ winrt::slim_lock_guard lock(m_Lock);
- RETURN_IF_FAILED (_CheckShutdownRequiresLock());
+ // Create the allocator if one doesn't exist
+ if (m_allocatorUsage == MFSampleAllocatorUsage_UsesProvidedAllocator)
+ {
+ RETURN_HR_IF_NULL_MSG(E_POINTER, m_spSampleAllocator, "Sample allocator is not set");
+ }
+ else
+ {
+ RETURN_IF_FAILED(MFCreateVideoSampleAllocatorEx(IID_PPV_ARGS(&m_spSampleAllocator)));
+ }
- if (SUCCEEDED(hr))
- {
- *pState = (_isSelected ? MF_STREAM_STATE_RUNNING : MF_STREAM_STATE_STOPPED);
- }
+ wil::com_ptr_nothrow<IMFMediaTypeHandler> spMTHandler;
+ RETURN_IF_FAILED(m_spStreamDesc->GetMediaTypeHandler(&spMTHandler));
- return hr;
-}
+ wil::com_ptr_nothrow<IMFMediaType> spMediaType;
+ UINT32 width, height;
+ GUID subType;
+ RETURN_IF_FAILED(spMTHandler->GetCurrentMediaType(&spMediaType));
+ RETURN_IF_FAILED(spMediaType->GetGUID(MF_MT_SUBTYPE, &subType));
+ MFGetAttributeSize(spMediaType.get(), MF_MT_FRAME_SIZE, &width, &height);
-HRESULT
-SimpleMediaStream::Shutdown(
- )
-{
- HRESULT hr = S_OK;
- auto lock = _critSec.Lock();
+ DEBUG_MSG(L"Initialize sample allocator for mediatype: %s, %dx%d ", winrt::to_hstring(subType).data(), width, height);
+ RETURN_IF_FAILED(m_spSampleAllocator->InitializeSampleAllocator(10, spMediaType.get()));
+ if (m_spFrameGenerator == nullptr)
+ {
+ m_spFrameGenerator = wil::make_unique_nothrow<SimpleFrameGenerator>();
+ RETURN_IF_NULL_ALLOC_MSG(m_spFrameGenerator, "Fail to create SimpleFrameGenerator");
+ }
+ RETURN_IF_FAILED(m_spFrameGenerator->Initialize(spMediaType.get()));
+
+ // Post MEStreamStarted event to signal stream has started
+ RETURN_IF_FAILED(m_spEventQueue->QueueEventParamVar(MEStreamStarted, GUID_NULL, S_OK, nullptr));
- _isShutdown = true;
- _parent.Reset();
+ return S_OK;
+ }
- if (_spEventQueue != nullptr)
+ HRESULT SimpleMediaStream::Stop()
{
- hr = _spEventQueue->Shutdown();
- _spEventQueue.Reset();
+ winrt::slim_lock_guard lock(m_Lock);
+
+ // Post MEStreamStopped event to signal stream has stopped
+ RETURN_IF_FAILED(m_spEventQueue->QueueEventParamVar(MEStreamStopped, GUID_NULL, S_OK, nullptr));
+ return S_OK;
}
- _spAttributes.Reset();
- _spMediaType.Reset();
- _spStreamDesc.Reset();
+ HRESULT SimpleMediaStream::Shutdown()
+ {
+ winrt::slim_lock_guard lock(m_Lock);
- _isSelected = false;
+ m_bIsShutdown = true;
+ m_parent.reset();
- return hr;
-}
+ if (m_spEventQueue != nullptr)
+ {
+ m_spEventQueue->Shutdown();
+ m_spEventQueue.reset();
+ }
-HRESULT
-SimpleMediaStream::_CheckShutdownRequiresLock(
- )
-{
- if (_isShutdown)
- {
- return MF_E_SHUTDOWN;
+ m_spAttributes.reset();
+ m_spStreamDesc.reset();
+
+ m_streamState = MF_STREAM_STATE_STOPPED;
+
+ return S_OK;
}
- if (_spEventQueue == nullptr)
+ HRESULT SimpleMediaStream::SetSampleAllocator(IMFVideoSampleAllocator* pAllocator)
{
- return E_UNEXPECTED;
+ winrt::slim_lock_guard lock(m_Lock);
+
+ if (m_streamState == MF_STREAM_STATE_RUNNING)
+ {
+ RETURN_HR_MSG(MF_E_INVALIDREQUEST, "Cannot update allocator when the stream is streaming");
+ }
+ m_spSampleAllocator.reset();
+ m_spSampleAllocator = pAllocator;
+ return S_OK;
}
- return S_OK;
-}
-HRESULT
-SimpleMediaStream::_SetStreamAttributes(
- _In_ IMFAttributes *pAttributeStore
- )
-{
- HRESULT hr = S_OK;
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+ // Private methods
- if (nullptr == pAttributeStore)
+ HRESULT SimpleMediaStream::_CheckShutdownRequiresLock()
{
- return E_INVALIDARG;
+ if (m_bIsShutdown)
+ {
+ return MF_E_SHUTDOWN;
+ }
+
+ if (m_spEventQueue == nullptr)
+ {
+ return E_UNEXPECTED;
+
+ }
+ return S_OK;
}
- 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));
+ HRESULT SimpleMediaStream::_SetStreamAttributes(
+ _In_ IMFAttributes* pAttributeStore
+ )
+ {
+ RETURN_HR_IF_NULL(E_INVALIDARG, pAttributeStore);
- return hr;
-}
+ RETURN_IF_FAILED(pAttributeStore->SetGUID(MF_DEVICESTREAM_STREAM_CATEGORY, PINNAME_VIDEO_CAPTURE));
+ RETURN_IF_FAILED(pAttributeStore->SetUINT32(MF_DEVICESTREAM_STREAM_ID, m_dwStreamId));
+ RETURN_IF_FAILED(pAttributeStore->SetUINT32(MF_DEVICESTREAM_FRAMESERVER_SHARED, 1));
+ RETURN_IF_FAILED(pAttributeStore->SetUINT32(MF_DEVICESTREAM_ATTRIBUTE_FRAMESOURCE_TYPES, MFFrameSourceTypes::MFFrameSourceTypes_Color));
-HRESULT
-SimpleMediaStream::_SetStreamDescriptorAttributes(
- _In_ IMFAttributes *pAttributeStore
- )
-{
- HRESULT hr = S_OK;
+ return S_OK;
+ }
- if (nullptr == pAttributeStore)
+ HRESULT SimpleMediaStream::_SetStreamDescriptorAttributes(
+ _In_ IMFAttributes* pAttributeStore
+ )
{
- return E_INVALIDARG;
+ RETURN_HR_IF_NULL(E_INVALIDARG, pAttributeStore);
+
+ RETURN_IF_FAILED(pAttributeStore->SetGUID(MF_DEVICESTREAM_STREAM_CATEGORY, PINNAME_VIDEO_CAPTURE));
+ RETURN_IF_FAILED(pAttributeStore->SetUINT32(MF_DEVICESTREAM_STREAM_ID, m_dwStreamId));
+ RETURN_IF_FAILED(pAttributeStore->SetUINT32(MF_DEVICESTREAM_FRAMESERVER_SHARED, 1));
+ RETURN_IF_FAILED(pAttributeStore->SetUINT32(MF_DEVICESTREAM_ATTRIBUTE_FRAMESOURCE_TYPES, MFFrameSourceTypes::MFFrameSourceTypes_Color));
+
+ return S_OK;
}
- 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;
}
-
diff --git a/general/SimpleMediaSource/MediaSource/SimpleMediaStream.h b/general/SimpleMediaSource/MediaSource/SimpleMediaStream.h
index 56351f47..70d20ec3 100644
--- a/general/SimpleMediaSource/MediaSource/SimpleMediaStream.h
+++ b/general/SimpleMediaSource/MediaSource/SimpleMediaStream.h
@@ -1,54 +1,69 @@
-#pragma once
+//
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
-#include "stdafx.h"
+#ifndef SIMPLEMEDIASTREAM_H
+#define SIMPLEMEDIASTREAM_H
-class SimpleMediaSource;
+#include "SimpleMediaSource.h"
-class SimpleMediaStream : public RuntimeClass<
- RuntimeClassFlags<ClassicCom>,
- IMFMediaEventGenerator,
- IMFMediaStream,
- IMFMediaStream2>
+namespace winrt::WindowsSample::implementation
{
- friend class SimpleMediaSource;
+ struct SimpleMediaStream : winrt::implements<SimpleMediaStream, IMFMediaStream2>
+ {
+ friend struct 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);
+ public:
+ // IMFMediaEventGenerator
+ IFACEMETHODIMP BeginGetEvent(IMFAsyncCallback* pCallback, IUnknown* punkState) override;
+ IFACEMETHODIMP EndGetEvent(IMFAsyncResult* pResult, IMFMediaEvent** ppEvent) override;
+ IFACEMETHODIMP GetEvent(DWORD dwFlags, IMFMediaEvent** ppEvent) override;
+ IFACEMETHODIMP QueueEvent(MediaEventType met, REFGUID guidExtendedType, HRESULT hrStatus, const PROPVARIANT* pvValue) override;
- // IMFMediaStream
- IFACEMETHOD(GetMediaSource)(IMFMediaSource **ppMediaSource);
- IFACEMETHOD(GetStreamDescriptor)(IMFStreamDescriptor **ppStreamDescriptor);
- IFACEMETHOD(RequestSample)(IUnknown *pToken);
+ // IMFMediaStream
+ IFACEMETHODIMP GetMediaSource(IMFMediaSource** ppMediaSource) override;
+ IFACEMETHODIMP GetStreamDescriptor(IMFStreamDescriptor** ppStreamDescriptor) override;
+ IFACEMETHODIMP RequestSample(IUnknown* pToken) override;
- // IMFMediaStream2
- IFACEMETHOD(SetStreamState)(MF_STREAM_STATE state);
- IFACEMETHOD(GetStreamState)(_Out_ MF_STREAM_STATE *pState);
+ // IMFMediaStream2
+ IFACEMETHODIMP SetStreamState(_In_ MF_STREAM_STATE state) override;
+ IFACEMETHODIMP GetStreamState(_Out_ MF_STREAM_STATE* pState) override;
- // Non-interface methods.
- HRESULT RuntimeClassInitialize(_In_ SimpleMediaSource* pSource);
- HRESULT Shutdown();
+ // Non-interface methods.
+ HRESULT Initialize(_In_ SimpleMediaSource* pSource, _In_ DWORD streamId, _In_ MFSampleAllocatorUsage allocatorUsage);
+ HRESULT Start();
+ HRESULT Stop();
+ HRESULT Shutdown();
+ HRESULT SetSampleAllocator(_In_ IMFVideoSampleAllocator* pAllocator);
+ DWORD Id() const { return m_dwStreamId; }
+ MFSampleAllocatorUsage SampleAlloactorUsage() const { return m_allocatorUsage; }
-protected:
- HRESULT _CheckShutdownRequiresLock();
- HRESULT _SetStreamAttributes(IMFAttributes* pAttributeStore);
- HRESULT _SetStreamDescriptorAttributes(IMFAttributes* pAttributeStore);
+ void SetRGBMask(ULONG rgbMask) { winrt::slim_lock_guard lock(m_Lock); m_rgbMask = rgbMask; }
+ ULONG GetRGBMask() { winrt::slim_lock_guard lock(m_Lock); return m_rgbMask; }
+ protected:
+ HRESULT _CheckShutdownRequiresLock();
+ HRESULT _SetStreamAttributes(IMFAttributes* pAttributeStore);
+ HRESULT _SetStreamDescriptorAttributes(IMFAttributes* pAttributeStore);
- CriticalSection _critSec;
+ private:
+ winrt::slim_mutex m_Lock;
- ComPtr<IMFMediaSource> _parent;
- ComPtr<IMFMediaEventQueue> _spEventQueue;
- ComPtr<IMFAttributes> _spAttributes;
- ComPtr<IMFMediaType> _spMediaType;
- ComPtr<IMFStreamDescriptor> _spStreamDesc;
- bool _isShutdown = false;
- bool _isSelected = false;
+ wil::com_ptr_nothrow<IMFMediaSource> m_parent;
+ wil::com_ptr_nothrow<IMFMediaEventQueue> m_spEventQueue;
+ wil::com_ptr_nothrow<IMFAttributes> m_spAttributes;
+ wil::com_ptr_nothrow<IMFStreamDescriptor> m_spStreamDesc;
+ wil::com_ptr_nothrow<IMFVideoSampleAllocator> m_spSampleAllocator;
+ wistd::unique_ptr<SimpleFrameGenerator> m_spFrameGenerator;
- const DWORD STREAMINDEX = 0; // since there is only one stream
-};
+ bool m_bIsShutdown = false;
+ MF_STREAM_STATE m_streamState = MF_STREAM_STATE_STOPPED;
+ ULONG m_rgbMask = KSPROPERTY_SIMPLEMEDIASOURCE_CUSTOMCONTROL_COLORMODE_BLUE;
+ DWORD m_dwStreamId;
+ MFSampleAllocatorUsage m_allocatorUsage;
+ };
+}
+
+#endif
diff --git a/general/SimpleMediaSource/MediaSource/dllMain.cpp b/general/SimpleMediaSource/MediaSource/dllMain.cpp
index aed44eb0..f021b4aa 100644
--- a/general/SimpleMediaSource/MediaSource/dllMain.cpp
+++ b/general/SimpleMediaSource/MediaSource/dllMain.cpp
@@ -1,35 +1,68 @@
-/// <copyright file="dllmain.cpp" company="Microsoft">
-/// Copyright (c) Microsoft Corporation. All rights reserved.
-/// </copyright>
+//
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+
// dllmain.cpp : Defines the entry point for the DLL application.
-#include "stdafx.h"
+#include "pch.h"
-#include <wrl\module.h>
+HINSTANCE g_hInst;
-#if !defined(__WRL_CLASSIC_COM__)
-STDAPI DllGetActivationFactory(_In_ HSTRING activatibleClassId, _COM_Outptr_ IActivationFactory** factory)
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, _COM_Outptr_ void** ppv)
{
- return Module<InProc>::GetModule().GetActivationFactory(activatibleClassId, factory);
-}
+ try
+ {
+ *ppv = nullptr;
+
+ if (rclsid == __uuidof(winrt::WindowsSample::implementation::SimpleMediaSourceActivate))
+ {
+ return winrt::make_self<SimpleMediaSourceActivateFactory>()->QueryInterface(riid, ppv);
+ }
+
+#ifdef _WRL_MODULE_H_
+ return ::Microsoft::WRL::Module<::Microsoft::WRL::InProc>::GetModule().GetClassObject(rclsid, riid, ppv);
+#else
+ return winrt::hresult_class_not_available().to_abi();
#endif
+ }
+ catch (...)
+ {
+ return winrt::to_hresult();
+ }
+}
-#if !defined(__WRL_WINRT_STRICT__)
-STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, _COM_Outptr_ void** ppv)
+bool __stdcall winrt_can_unload_now() noexcept
{
- return Module<InProc>::GetModule().GetClassObject(rclsid, riid, ppv);
+ if (winrt::get_module_lock())
+ {
+ return false;
+ }
+
+ winrt::clear_factory_cache();
+ return true;
}
-#endif
-STDAPI DllCanUnloadNow()
+int32_t __stdcall WINRT_CanUnloadNow() noexcept
{
- return Module<InProc>::GetModule().Terminate() ? S_OK : S_FALSE;
+#ifdef _WRL_MODULE_H_
+ if (!::Microsoft::WRL::Module<::Microsoft::WRL::InProc>::GetModule().Terminate())
+ {
+ return 1;
+ }
+#endif
+
+ return winrt_can_unload_now() ? 0 : 1;
}
STDAPI_(BOOL) DllMain(_In_opt_ HINSTANCE hinst, DWORD reason, _In_opt_ void*)
{
- if (reason == DLL_PROCESS_ATTACH)
+ switch (reason)
{
- DisableThreadLibraryCalls(hinst);
+ case DLL_PROCESS_ATTACH:
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ break;
+ case DLL_PROCESS_DETACH:
+ g_hInst = hinst;
}
return TRUE;
}
diff --git a/general/SimpleMediaSource/MediaSource/module.def b/general/SimpleMediaSource/MediaSource/module.def
index ddeb3eac..16e9b4fe 100644
--- a/general/SimpleMediaSource/MediaSource/module.def
+++ b/general/SimpleMediaSource/MediaSource/module.def
@@ -1,6 +1,3 @@
-LIBRARY
-
EXPORTS
- DllGetActivationFactory PRIVATE
+ DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
DllGetClassObject PRIVATE
- DllCanUnloadNow PRIVATE
diff --git a/general/SimpleMediaSource/MediaSource/pch.cpp b/general/SimpleMediaSource/MediaSource/pch.cpp
new file mode 100644
index 00000000..e40b6b12
--- /dev/null
+++ b/general/SimpleMediaSource/MediaSource/pch.cpp
@@ -0,0 +1,26 @@
+//
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+
+// pch.cpp: source file corresponding to the pre-compiled header
+#include "pch.h"
+
+// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.
+
+namespace winrt
+{
+ template<> bool is_guid_of<IMFMediaSourceEx>(guid const& id) noexcept
+ {
+ return is_guid_of<IMFMediaSourceEx, IMFMediaSource, IMFMediaEventGenerator>(id);
+ }
+
+ template<> bool is_guid_of<IMFMediaStream2>(guid const& id) noexcept
+ {
+ return is_guid_of<IMFMediaStream2, IMFMediaStream, IMFMediaEventGenerator>(id);
+ }
+
+ template<> bool is_guid_of<IMFActivate>(guid const& id) noexcept
+ {
+ return is_guid_of<IMFActivate, IMFAttributes>(id);
+ }
+} \ No newline at end of file
diff --git a/general/SimpleMediaSource/MediaSource/pch.h b/general/SimpleMediaSource/MediaSource/pch.h
new file mode 100644
index 00000000..dc59629c
--- /dev/null
+++ b/general/SimpleMediaSource/MediaSource/pch.h
@@ -0,0 +1,82 @@
+// pch.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 <unknwn.h>
+#include <windows.h>
+#include <propvarutil.h>
+#include <ole2.h>
+#include <initguid.h>
+#include <ks.h>
+#include <ksproxy.h>
+#include <ksmedia.h>
+#include <mfapi.h>
+#include <mferror.h>
+#include <mfidl.h>
+#include <mfreadwrite.h>
+#include <nserror.h>
+#include <winmeta.h>
+#include <d3d9types.h>
+
+#define RESULT_DIAGNOSTICS_LEVEL 4 // include function name
+
+#include <wil\cppwinrt.h> // must be before the first C++ WinRT header, ref:https://github.com/Microsoft/wil/wiki/Error-handling-helpers
+#include <wil\result.h>
+#include <wil\com.h>
+
+#include "SimpleFrameGenerator.h"
+#include "SimpleMediaStream.h"
+#include "SimpleMediaSource.h"
+#include "SimpleMediaSourceActivate.h"
+
+inline void DebugPrint(LPCWSTR szFormat, ...)
+{
+ WCHAR szBuffer[MAX_PATH] = { 0 };
+
+ va_list pArgs;
+ va_start(pArgs, szFormat);
+ StringCbVPrintf(szBuffer, sizeof(szBuffer), szFormat, pArgs);
+ va_end(pArgs);
+ OutputDebugStringW(szBuffer);
+}
+
+#define DEBUG_MSG(msg,...) \
+{\
+ DebugPrint(L"[%s@%d] ", TEXT(__FUNCTION__), __LINE__);\
+ DebugPrint(msg, __VA_ARGS__);\
+ DebugPrint(L"\n");\
+}\
+
+namespace wilEx
+{
+ //template <typename T>
+ //using make_unique_cotaskmem_array = unique_any_array_ptr<typename details::element_traits<T>::type>;
+
+ template<typename T>
+ wil::unique_cotaskmem_array_ptr<T> make_unique_cotaskmem_array(size_t numOfElements)
+ {
+ wil::unique_cotaskmem_array_ptr<T> arr;
+ size_t cb = sizeof(wil::details::element_traits<T>::type) * numOfElements;
+ void* ptr = ::CoTaskMemAlloc(cb);
+ if (ptr != nullptr)
+ {
+ ZeroMemory(ptr, cb);
+ arr.reset(reinterpret_cast<typename wil::details::element_traits<T>::type*>(ptr), numOfElements);
+ }
+ return arr;
+ }
+};
+
+namespace winrt
+{
+ template<> bool is_guid_of<IMFMediaSourceEx>(guid const& id) noexcept;
+
+ template<> bool is_guid_of<IMFMediaStream2>(guid const& id) noexcept;
+
+ template<> bool is_guid_of<IMFActivate>(guid const& id) noexcept;
+};
+
+
diff --git a/general/SimpleMediaSource/MediaSource/stdafx.cpp b/general/SimpleMediaSource/MediaSource/stdafx.cpp
deleted file mode 100644
index dc97a45b..00000000
--- a/general/SimpleMediaSource/MediaSource/stdafx.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-/// <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
deleted file mode 100644
index 73bec0b4..00000000
--- a/general/SimpleMediaSource/MediaSource/stdafx.h
+++ /dev/null
@@ -1,76 +0,0 @@
-// 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 <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 <ks.h>
-#include <ksmedia.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>
-
-using namespace Microsoft::WRL;
-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
-
diff --git a/general/SimpleMediaSource/SimpleMediaSource.sln b/general/SimpleMediaSource/SimpleMediaSource.sln
index c93b8c42..f6bd620c 100644
--- a/general/SimpleMediaSource/SimpleMediaSource.sln
+++ b/general/SimpleMediaSource/SimpleMediaSource.sln
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.27703.2026
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31129.286
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleMediaSource", "MediaSource\MediaSource.vcxproj", "{43AD9BF7-E765-48FE-9826-71A8F2CB12DD}"
EndProject
diff --git a/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.vcxproj b/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.vcxproj
index 38e21ccd..bb32647a 100644
--- a/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.vcxproj
+++ b/general/SimpleMediaSource/SimpleMediaSourceDriver/SimpleMediaSourceDriver.vcxproj
@@ -75,6 +75,7 @@
<Configuration>Debug</Configuration>
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
<RootNamespace>SimpleMediaSourceDriver</RootNamespace>
+ <WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
</PropertyGroup>
<PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
@@ -205,6 +206,9 @@
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\OneCoreUAP.lib</AdditionalDependencies>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@@ -215,6 +219,9 @@
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\OneCoreUAP.lib</AdditionalDependencies>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@@ -225,6 +232,9 @@
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\OneCoreUAP.lib</AdditionalDependencies>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
@@ -235,6 +245,9 @@
<Link>
<AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\OneCoreUAP.lib</AdditionalDependencies>
</Link>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
<ClCompile>