summaryrefslogtreecommitdiff
path: root/avstream
diff options
context:
space:
mode:
Diffstat (limited to 'avstream')
-rw-r--r--avstream/avscamera/Package/package.VcxProj4
-rw-r--r--avstream/avscamera/mft0/MFT0Impl.cpp4
-rw-r--r--avstream/avscamera/mft0/stdafx.h5
-rw-r--r--avstream/avscamera/sys/AvsCamera.cpp25
-rw-r--r--avstream/avscamera/sys/AvsCamera.vcxproj4
-rw-r--r--avstream/avscamera/sys/AvsCameraFilter.cpp11
-rw-r--r--avstream/avscamera/sys/Capture.cpp17
-rw-r--r--avstream/avscamera/sys/Common.h6
-rw-r--r--avstream/avscamera/sys/Device.cpp22
-rw-r--r--avstream/avscamera/sys/Device.h13
-rw-r--r--avstream/avscamera/sys/PreviewHwSim.cpp32
-rw-r--r--avstream/avscamera/sys/PreviewHwSim.h4
-rw-r--r--avstream/avscamera/sys/Sensor.cpp49
-rw-r--r--avstream/avscamera/sys/Sensor.h14
-rw-r--r--avstream/avscamera/sys/SensorSimulation.cpp82
-rw-r--r--avstream/avscamera/sys/SensorSimulation.h8
-rw-r--r--avstream/avscamera/sys/VideoHwSim.cpp49
-rw-r--r--avstream/avscamera/sys/VideoHwSim.h4
-rw-r--r--avstream/avscamera/sys/avscamera.inx (renamed from avstream/avscamera/sys/avscamera.inf)bin26816 -> 25260 bytes
-rw-r--r--avstream/avscamera/sys/filter.cpp183
-rw-r--r--avstream/avscamera/sys/filter.h8
-rw-r--r--avstream/avscamera/sys/hwsim.cpp46
-rw-r--r--avstream/avscamera/sys/imagecapture.cpp4
-rw-r--r--avstream/avshws/README.md11
-rw-r--r--avstream/avshws/avshws.inf173
-rw-r--r--avstream/avshws/avshws.inxbin0 -> 5944 bytes
-rw-r--r--avstream/avshws/avshws.sln5
-rw-r--r--avstream/avshws/avshws.vcxproj4
-rw-r--r--avstream/avshws/capture.cpp2
-rw-r--r--avstream/avshws/device.cpp25
-rw-r--r--avstream/avshws/hwsim.cpp2
-rw-r--r--avstream/avshws/makefile15
-rw-r--r--avstream/avssamp/Filter.cpp6
-rw-r--r--avstream/avssamp/avssamp.cpp16
-rw-r--r--avstream/avssamp/avssamp.inf93
-rw-r--r--avstream/avssamp/avssamp.inxbin0 -> 3226 bytes
-rw-r--r--avstream/avssamp/avssamp.vcxproj2
-rw-r--r--avstream/avssamp/makefile15
-rw-r--r--avstream/avssamp/video.cpp10
-rw-r--r--avstream/avssamp/wave.cpp2
-rw-r--r--avstream/sampledevicemft/basepin.cpp171
-rw-r--r--avstream/sampledevicemft/basepin.h64
-rw-r--r--avstream/sampledevicemft/common.h11
-rw-r--r--avstream/sampledevicemft/contosodevice.h28
-rw-r--r--avstream/sampledevicemft/custompin.cpp2
-rw-r--r--avstream/sampledevicemft/dllmain.cpp24
-rw-r--r--avstream/sampledevicemft/multipinmft.cpp60
-rw-r--r--avstream/sampledevicemft/multipinmft.h20
-rw-r--r--avstream/sampledevicemft/multipinmft.vcxproj8
-rw-r--r--avstream/sampledevicemft/multipinmft.vcxproj.Filters1
-rw-r--r--avstream/sampledevicemft/multipinmfthelpers.cpp396
-rw-r--r--avstream/sampledevicemft/multipinmfthelpers.h211
-rw-r--r--avstream/sampledevicemft/multipinmftutils.cpp86
-rw-r--r--avstream/sampledevicemft/packages.config4
-rw-r--r--avstream/sampledevicemft/stdafx.h7
55 files changed, 1384 insertions, 684 deletions
diff --git a/avstream/avscamera/Package/package.VcxProj b/avstream/avscamera/Package/package.VcxProj
index 5b8aa6ef..92690b1a 100644
--- a/avstream/avscamera/Package/package.VcxProj
+++ b/avstream/avscamera/Package/package.VcxProj
@@ -42,22 +42,18 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
- <DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
- <DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
- <DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
- <DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/avstream/avscamera/mft0/MFT0Impl.cpp b/avstream/avscamera/mft0/MFT0Impl.cpp
index 992be0e9..26d40f99 100644
--- a/avstream/avscamera/mft0/MFT0Impl.cpp
+++ b/avstream/avscamera/mft0/MFT0Impl.cpp
@@ -1950,14 +1950,14 @@ HRESULT CSocMft0::ParseMetadata_FaceDetection(
}
PMETADATA_FACEDATA pFaceData = (PMETADATA_FACEDATA)(pFaceHeader + 1);
UINT32 cbRectSize = sizeof(FaceRectInfoBlobHeader) + (sizeof(FaceRectInfo) * (pFaceHeader->Count));
- BYTE *pRectBuf = new BYTE[cbRectSize];
+ BYTE *pRectBuf = new (std::nothrow) BYTE[cbRectSize];
if (pRectBuf == NULL)
{
return E_OUTOFMEMORY;
}
UINT32 cbCharSize = sizeof(FaceCharacterizationBlobHeader) + (sizeof(FaceCharacterization) * (pFaceHeader->Count));
- BYTE *pCharBuf = new BYTE[cbCharSize];
+ BYTE *pCharBuf = new (std::nothrow) BYTE[cbCharSize];
if (pCharBuf == NULL)
{
delete[] pRectBuf;
diff --git a/avstream/avscamera/mft0/stdafx.h b/avstream/avscamera/mft0/stdafx.h
index 037376ec..6d784805 100644
--- a/avstream/avscamera/mft0/stdafx.h
+++ b/avstream/avscamera/mft0/stdafx.h
@@ -16,7 +16,12 @@
#endif
#include "targetver.h"
+#if (NTDDI_VERSION >= NTDDI_WIN10_VB)
+#pragma message("MFT0 is deprecated for this target Windows version and beyond- Change project settings to target an older version of Windows")
+#endif
+
#if (NTDDI_VERSION <= NTDDI_WIN7)
+// TODO: disable the MFT0 conditional to the target system version
#pragma message("MFT0 is in not supported in this target Windows version - Change project settings to target a newer version of Windows")
#endif
diff --git a/avstream/avscamera/sys/AvsCamera.cpp b/avstream/avscamera/sys/AvsCamera.cpp
index 3563b3dd..3c51323f 100644
--- a/avstream/avscamera/sys/AvsCamera.cpp
+++ b/avstream/avscamera/sys/AvsCamera.cpp
@@ -29,13 +29,7 @@ PVOID operator new
POOL_TYPE poolType
)
{
- PVOID result = ExAllocatePoolWithTag(poolType,iSize,'wNCK');
-
- if (result) {
- RtlZeroMemory(result,iSize);
- }
-
- return result;
+ return ExAllocatePoolZero(poolType,iSize,'wNCK');
}
PVOID operator new
@@ -48,13 +42,7 @@ PVOID operator new
ULONG tag
)
{
- PVOID result = ExAllocatePoolWithTag(poolType,iSize,tag);
-
- if (result) {
- RtlZeroMemory(result,iSize);
- }
-
- return result;
+ return ExAllocatePoolZero(poolType,iSize,tag);
}
PVOID
@@ -67,14 +55,7 @@ operator new[](
ULONG tag
)
{
- PVOID result = ExAllocatePoolWithTag(poolType, iSize, tag);
-
- if (result)
- {
- RtlZeroMemory(result, iSize);
- }
-
- return result;
+ return ExAllocatePoolZero(poolType, iSize, tag);
}
/*++
diff --git a/avstream/avscamera/sys/AvsCamera.vcxproj b/avstream/avscamera/sys/AvsCamera.vcxproj
index 326b1848..81d0078b 100644
--- a/avstream/avscamera/sys/AvsCamera.vcxproj
+++ b/avstream/avscamera/sys/AvsCamera.vcxproj
@@ -232,7 +232,7 @@
<ResourceCompile Include="AvsCamera.rc" />
</ItemGroup>
<ItemGroup>
- <Inf Exclude="@(Inf)" Include="*.inf" />
+ <Inf Exclude="@(Inf)" Include="*.inf;*.inx" />
<FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
</ItemGroup>
<ItemGroup>
@@ -244,4 +244,4 @@
<ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-</Project> \ No newline at end of file
+</Project>
diff --git a/avstream/avscamera/sys/AvsCameraFilter.cpp b/avstream/avscamera/sys/AvsCameraFilter.cpp
index af25b691..1a41997a 100644
--- a/avstream/avscamera/sys/AvsCameraFilter.cpp
+++ b/avstream/avscamera/sys/AvsCameraFilter.cpp
@@ -221,7 +221,7 @@ DEFINE_KSPROPERTY_TABLE(ExtendedPropertyItems)
CCaptureFilter::SetRoiIspControl,
NULL, 0, NULL, NULL, 0
),
- DEFINE_PROP_ITEM(CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_ZOOM, CExtendedVidProcSetting, Zoom),
+ DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_ZOOM, CExtendedVidProcSetting, Zoom),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_VIDEOHDR, CExtendedProperty, VideoHDR ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_VFR, CExtendedProperty, VFR ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_ISO_ADVANCED, CExtendedVidProcSetting, IsoAdvanced ),
@@ -230,7 +230,8 @@ DEFINE_KSPROPERTY_TABLE(ExtendedPropertyItems)
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_OIS, CExtendedProperty, OpticalImageStabilization ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_ADVANCEDPHOTO, CExtendedProperty, AdvancedPhoto ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_PROFILE, CExtendedProfile, CameraProfile ),
- DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_VIDEOTEMPORALDENOISING, CExtendedProperty, VideoTemporalDenoising)
+ DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_VIDEOTEMPORALDENOISING, CExtendedProperty, VideoTemporalDenoising),
+ DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_RELATIVEPANELOPTIMIZATION, CExtendedProperty, RelativePanel)
};
// Front-facing cameras often have limited capabilities. One way to express that is to use a restricted automation table such as this one.
@@ -244,6 +245,7 @@ DEFINE_KSPROPERTY_TABLE(ExtendedPropertyItemsFFC)
DEFINE_PROP_ITEM_NO_SET( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_MAXVIDFPS_PHOTORES, CExtendedMaxVideoFpsForPhotoRes, MaxVideoFpsForPhotoRes ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_SCENEMODE, CExtendedProperty, SceneMode ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_TORCHMODE, CExtendedProperty, TorchMode ),
+ DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_IRTORCHMODE, CExtendedVidProcSetting, IRTorch ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_OPTIMIZATIONHINT, CExtendedProperty, OptimizationHint ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_WHITEBALANCEMODE, CExtendedVidProcSetting, WhiteBalance ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_EXPOSUREMODE, CExtendedVidProcSetting, Exposure ),
@@ -258,11 +260,12 @@ DEFINE_KSPROPERTY_TABLE(ExtendedPropertyItemsFFC)
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_ISO_ADVANCED, CExtendedVidProcSetting, IsoAdvanced ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_VIDEOSTABILIZATION, CExtendedProperty, VideoStabilization ),
DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_ADVANCEDPHOTO, CExtendedProperty, AdvancedPhoto ),
- DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_PROFILE, CExtendedProfile, CameraProfile )
+ DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_PROFILE, CExtendedProfile, CameraProfile ),
+ DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXTENDED_RELATIVEPANELOPTIMIZATION, CExtendedProperty, RelativePanel)
};
//--------------------------------------------------------------
-// Legacy Camera Contorl properties
+// Legacy Camera Control properties
DEFINE_KSPROPERTY_TABLE(CameraControlPropertyTable)
{
DEFINE_PROP_ITEM_WITH_VALUES(CCaptureFilter, KSPROPERTY_CAMERACONTROL_EXPOSURE, KSPROPERTY_CAMERACONTROL_S, Exposure, &ExposureValues),
diff --git a/avstream/avscamera/sys/Capture.cpp b/avstream/avscamera/sys/Capture.cpp
index e5d43ddd..25e6a5f8 100644
--- a/avstream/avscamera/sys/Capture.cpp
+++ b/avstream/avscamera/sys/Capture.cpp
@@ -266,7 +266,7 @@ Return Value:
(m_Pin->ConnectionFormat))->ImageInfoHeader);
m_VideoInfoHeader = reinterpret_cast <PKS_VIDEOINFOHEADER> (
- ExAllocatePoolWithTag (
+ ExAllocatePoolZero (
NonPagedPoolNx,
max(sizeof(KS_VIDEOINFOHEADER), ConnectionHeader->biSize + KS_SIZE_PREHEADER),
AVSHWS_POOLTAG
@@ -308,7 +308,7 @@ Return Value:
VideoInfoHeader);
m_VideoInfoHeader = reinterpret_cast <PKS_VIDEOINFOHEADER> (
- ExAllocatePoolWithTag (
+ ExAllocatePoolZero (
NonPagedPoolNx,
max(sizeof(KS_VIDEOINFOHEADER), KS_SIZE_VIDEOHEADER (ConnectionHeader)),
AVSHWS_POOLTAG
@@ -339,7 +339,7 @@ Return Value:
VideoInfoHeader2);
m_VideoInfoHeader = reinterpret_cast <PKS_VIDEOINFOHEADER> (
- ExAllocatePoolWithTag(
+ ExAllocatePoolZero(
NonPagedPoolNx,
max(sizeof(KS_VIDEOINFOHEADER), ConnectionHeader->bmiHeader.biSize + KS_SIZE_PREHEADER),
AVSHWS_POOLTAG
@@ -2100,7 +2100,18 @@ Return Value:
{
PAGED_CODE( );
+ // If the host process did not stop the pin, we need to do that before
+ // the CCapturePin object gets freed.
+ if (m_Pin->DeviceState != KSSTATE_STOP)
+ {
+ // Skip straight to the STOP state because our simulation doesn't
+ // really need the PAUSE and ACQUIRE transitions when stopping.
+ SetState(KSSTATE_STOP, m_Pin->DeviceState);
+ }
+
// Some reasonable default behavior.
+ GetFilter()->setPin(nullptr, m_Pin->Id);
+
return STATUS_SUCCESS;
}
diff --git a/avstream/avscamera/sys/Common.h b/avstream/avscamera/sys/Common.h
index fdcb1c48..7cde102f 100644
--- a/avstream/avscamera/sys/Common.h
+++ b/avstream/avscamera/sys/Common.h
@@ -23,11 +23,15 @@
#define _NO_SYS_GUID_OPERATOR_EQ_
+#ifdef NTDDI_VERSION
+#undef NTDDI_VERSION
+#endif //NTDDI_VERSION
+#define NTDDI_VERSION NTDDI_WIN10_VB
+
#include <stdio.h>
#include <stdlib.h>
#include <wdm.h>
-#include <wdmguid.h>
#include <windef.h>
#include <unknown.h>
#include <ks.h>
diff --git a/avstream/avscamera/sys/Device.cpp b/avstream/avscamera/sys/Device.cpp
index 99bc60ce..2741da08 100644
--- a/avstream/avscamera/sys/Device.cpp
+++ b/avstream/avscamera/sys/Device.cpp
@@ -33,6 +33,10 @@
#pragma code_seg("PAGE")
#endif // ALLOC_PRAGMA
+#ifndef DEVPKEY_Device_PanelId
+DEFINE_DEVPROPKEY(DEVPKEY_Device_PanelId, 0x8dbc9c86, 0x97a9, 0x4bff, 0x9b, 0xc6, 0xbf, 0xe9, 0x5d, 0x3e, 0x6d, 0xad, 2); // DEVPROP_TYPE_STRING
+#endif
+
CCaptureDevice::
CCaptureDevice (
_In_ PKSDEVICE Device
@@ -616,9 +620,12 @@ Return Value:
pld.Revision = 2;
pld.Panel = m_Context[i].AcpiPosition;
pld.Rotation = m_Context[i].AcpiRotation;
- static
- const
- GUID FFC_Filter = {STATIC_FrontCamera_Filter};
+ pld.CabinetNumber = 0;
+ WCHAR PanelId[MAX_PATH] = { 0 };
+ size_t cchDest = MAX_PATH;
+
+ IFFAILED_EXIT(
+ RtlStringCchPrintfW(PanelId, cchDest, L"{00000000-0000-0000-ffff-ffffffffffff}\\%04X\\%u", pld.CabinetNumber, PnpAcpiPanelSideMap[pld.Panel]));
IFFAILED_EXIT(
IoSetDeviceInterfacePropertyData(SymbolicLinkName,
@@ -629,6 +636,15 @@ Return Value:
sizeof(pld),
(PVOID)&pld)
);
+
+ // Also set Panel ID manually, because PnP does not do this for the interface currently
+ IoSetDeviceInterfacePropertyData(SymbolicLinkName,
+ &DEVPKEY_Device_PanelId,
+ LOCALE_NEUTRAL,
+ PLUGPLAY_PROPERTY_PERSISTENT,
+ DEVPROP_TYPE_STRING,
+ (ULONG)(wcslen(PanelId)+1)*sizeof(WCHAR),
+ (PVOID)PanelId);
}
// On a real device this object would be constructed whenever the sensor hardware is ready...
diff --git a/avstream/avscamera/sys/Device.h b/avstream/avscamera/sys/Device.h
index 95debada..c203f70e 100644
--- a/avstream/avscamera/sys/Device.h
+++ b/avstream/avscamera/sys/Device.h
@@ -34,6 +34,17 @@ struct CSensorContext
AcpiPldRotation AcpiRotation; // How the device is oriented with respect to the panel.
};
+static constexpr ULONG PnpAcpiPanelSideMap[]
+{
+ 1, // AcpiPldPanelTop
+ 2, // AcpiPldPanelBottom
+ 3, // AcpiPldPanelLeft
+ 4, // AcpiPldPanelRight
+ 5, // AcpiPldPanelFront
+ 6, // AcpiPldPanelBack
+ 0, // AcpiPldPanelUnknown
+};
+
class CCaptureDevice
{
protected:
@@ -393,7 +404,7 @@ public:
PDEVICE_OBJECT
GetDeviceObject();
- static IO_COMPLETION_ROUTINE CCaptureDevice::IrpSynchronousCompletion;
+ static IO_COMPLETION_ROUTINE IrpSynchronousCompletion;
virtual
NTSTATUS
diff --git a/avstream/avscamera/sys/PreviewHwSim.cpp b/avstream/avscamera/sys/PreviewHwSim.cpp
index 775c6b8d..f55ffa20 100644
--- a/avstream/avscamera/sys/PreviewHwSim.cpp
+++ b/avstream/avscamera/sys/PreviewHwSim.cpp
@@ -40,6 +40,7 @@ CPreviewHardwareSimulation::CPreviewHardwareSimulation(
_In_ LONG PinID
)
: CHardwareSimulation( Sensor, PinID )
+ , m_Illuminated(FALSE)
{
PAGED_CODE();
}
@@ -299,6 +300,11 @@ Return Value:
BytesLeft -= sizeof(CAMERA_METADATA_INTRINSICS);
}
+ // TODO: This metadata should only be exposed on a sensor category preview pin.
+ // It's possible I should derive a new preview sim to handle this; but for now
+ // we just populate the IR illumination state on every preview pin. Hopefully
+ // the app is smart enough to realize that this is meaningless if they have not
+ // selected an IR mediatype.
if (BytesLeft >= sizeof(KSCAMERA_METADATA_FRAMEILLUMINATION))
{
PKSCAMERA_METADATA_FRAMEILLUMINATION pPreviewIllumination =
@@ -308,7 +314,31 @@ Return Value:
pPreviewIllumination->Header.MetadataId = (ULONG)MetadataId_FrameIllumination;
pPreviewIllumination->Header.Size = sizeof(KSCAMERA_METADATA_FRAMEILLUMINATION);
- pPreviewIllumination->Flags = KSCAMERA_METADATA_FRAMEILLUMINATION_FLAG_ON;
+ // Toggle the Illumination state for an IR frame.
+ CExtendedVidProcSetting State;
+ (void) m_Sensor->GetIRTorch(&State);
+
+ if (State.Flags & KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALWAYS_ON)
+ {
+ m_Illuminated = TRUE;
+ pPreviewIllumination->Flags = KSCAMERA_METADATA_FRAMEILLUMINATION_FLAG_ON;
+ }
+ else if ((State.Flags & KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALTERNATING_FRAME_ILLUMINATION))
+ {
+ m_Illuminated = !m_Illuminated;
+ if (m_Illuminated)
+ {
+ pPreviewIllumination->Flags = KSCAMERA_METADATA_FRAMEILLUMINATION_FLAG_ON;
+ }
+ }
+ else
+ {
+ m_Illuminated = FALSE;
+ }
+
+ DBG_TRACE("Frame Illumination: Flags=0x%016llX, State=%s",
+ State.Flags,
+ (pPreviewIllumination->Flags==KSCAMERA_METADATA_FRAMEILLUMINATION_FLAG_ON ?"ON":"OFF"));
pMetadata->UsedSize += sizeof(KSCAMERA_METADATA_FRAMEILLUMINATION);
BytesLeft -= sizeof(KSCAMERA_METADATA_FRAMEILLUMINATION);
diff --git a/avstream/avscamera/sys/PreviewHwSim.h b/avstream/avscamera/sys/PreviewHwSim.h
index e5a4f536..1d26f692 100644
--- a/avstream/avscamera/sys/PreviewHwSim.h
+++ b/avstream/avscamera/sys/PreviewHwSim.h
@@ -43,7 +43,6 @@ public:
protected:
METADATA_PREVIEWAGGREGATION
- CPreviewHardwareSimulation::
GetMetadata();
VOID GetCaptureStats(
@@ -57,5 +56,8 @@ protected:
_Inout_ PKSSTREAM_HEADER pStreamHeader
);
+private:
+ BOOLEAN m_Illuminated;
+
};
diff --git a/avstream/avscamera/sys/Sensor.cpp b/avstream/avscamera/sys/Sensor.cpp
index 9215f6b6..654ea666 100644
--- a/avstream/avscamera/sys/Sensor.cpp
+++ b/avstream/avscamera/sys/Sensor.cpp
@@ -188,7 +188,7 @@ Initialize()
m_InterruptTime[i] = 0;
m_LastMappingsCompleted[i] = 0;
}
- return STATUS_SUCCESS;
+ return m_Device ? STATUS_SUCCESS : STATUS_INVALID_PARAMETER;
}
void
@@ -356,7 +356,7 @@ CreateSynthesizer(
if( NT_SUCCESS( Status ) )
{
- DBG_TRACE( "Setting Mounting Orientation to %d�", DbgRotation2Degrees(m_MountingOrientation) )
+ DBG_TRACE( "Setting Mounting Orientation to %d°", DbgRotation2Degrees(m_MountingOrientation) )
m_Synthesizer[ Pin->Id ]->SetRotation( m_MountingOrientation );
}
@@ -412,15 +412,17 @@ Return Value:
NTSTATUS Status = STATUS_SUCCESS;
LONG lPindex = Pin->Id;
+
+ // Hold off all image generation while we manipulate the capture pin and synthensizer arrays.
+ KScopedMutex Lock(m_SensorMutex);
+
//
// If we're the first pin to go into acquire (remember we can have
// a filter in another graph going simultaneously), grab the resources for Preview
//
- if( InterlockedCompareExchangePointer(
- (PVOID *) &m_CapturePin[lPindex],
- CapturePin,
- nullptr) == nullptr)
+ if (m_CapturePin[lPindex] == nullptr)
{
+ m_CapturePin[lPindex] = CapturePin;
m_VideoInfoHeader[lPindex] = VideoInfoHeader;
//
@@ -449,7 +451,6 @@ Return Value:
//
// If everything has succeeded thus far, set the capture pin.
//
- m_CapturePin[lPindex] = CapturePin;
*pSim = m_HardwareSimulation[lPindex];
}
@@ -460,6 +461,8 @@ Return Value:
// acquired.
//
ReleaseHardwareResources(Pin);
+ *pSim = nullptr;
+ m_CapturePin[lPindex] = nullptr;
}
}
else
@@ -1088,20 +1091,23 @@ Return Value:
void
CSensor::
-SetSynthesizerAttribute(
- CSynthesizer::Attribute Attrib,
- LONGLONG Info,
- LONG PinId
+SetSynthesizerAttributeList(
+ _In_ size_t Count,
+ _In_ SynthesizerAttributeEntry AttributeList[]
)
{
PAGED_CODE();
-
- for( ULONG Pin=0; IsValidIndex(Pin); Pin++ )
+ // Syncrhonize access to sensor.
+ KScopedMutex Lock(m_SensorMutex);
+ for (size_t item = 0; item < Count; item++)
{
- if( (Pin==(ULONG)PinId || IsStillIndex(Pin)) &&
- m_Synthesizer[Pin] )
+ for (ULONG Pin = 0; IsValidIndex(Pin); Pin++)
{
- m_Synthesizer[Pin]->Set( Attrib, Info );
+ if ((Pin == (ULONG)AttributeList[item].PinId || IsStillIndex(Pin)) &&
+ m_Synthesizer[Pin])
+ {
+ m_Synthesizer[Pin]->Set(AttributeList[item].Attrib, AttributeList[item].Info);
+ }
}
}
}
@@ -1140,11 +1146,15 @@ Return Value:
DBG_ENTER( "( Pin=%d )\n", Pin->Id ) ;
LONG lPindex = Pin->Id;
+
//
// Blow away the image synth.
//
m_HardwareSimulation[lPindex]->Reset();
+ // Hold off all image generation while we free the capture pin and synthensizer arrays.
+ KScopedMutex Lock(m_SensorMutex);
+
SAFE_DELETE( m_Synthesizer[lPindex] );
m_VideoInfoHeader[lPindex] = NULL;
@@ -1152,10 +1162,7 @@ Return Value:
// Release our "lock" on hardware resources. This will allow another
// pin (perhaps in another graph) to acquire them.
//
- InterlockedExchangePointer(
- (PVOID *) &(m_CapturePin[lPindex]),
- nullptr
- );
+ m_CapturePin[lPindex] = nullptr;
DBG_LEAVE( "( Pin=%d )\n", Pin->Id ) ;
}
@@ -1322,6 +1329,7 @@ DEFINE_NULL_PROPERTY_GET(CSensor, KSPROPERTY_CAMERACONTROL_IMAGE_PIN_CAPABILITY_
DEFINE_NULL_PROPERTY(CSensor, CExtendedProperty, TriggerTime)
DEFINE_NULL_PROPERTY(CSensor, CExtendedProperty, TorchMode)
+DEFINE_NULL_PROPERTY(CSensor, CExtendedVidProcSetting, IRTorch)
DEFINE_NULL_PROPERTY(CSensor, CExtendedProperty, ExtendedFlash)
DEFINE_NULL_PROPERTY_GET(CSensor, CExtendedProperty, PhotoFrameRate)
@@ -1352,6 +1360,7 @@ DEFINE_NULL_PROPERTY(CSensor, CExtendedProperty, OptimizationHint)
DEFINE_NULL_PROPERTY(CSensor, CExtendedProperty, AdvancedPhoto)
DEFINE_NULL_PROPERTY(CSensor, CExtendedVidProcSetting, FaceDetection)
DEFINE_NULL_PROPERTY(CSensor, CExtendedProperty, VideoTemporalDenoising)
+DEFINE_NULL_PROPERTY(CSensor, CExtendedProperty, RelativePanel)
DEFINE_NULL_PROPERTY(CSensor, KSPROPERTY_CAMERACONTROL_VIDEOSTABILIZATION_MODE_S, VideoStabMode)
diff --git a/avstream/avscamera/sys/Sensor.h b/avstream/avscamera/sys/Sensor.h
index 327b860a..31b0f3a2 100644
--- a/avstream/avscamera/sys/Sensor.h
+++ b/avstream/avscamera/sys/Sensor.h
@@ -517,8 +517,18 @@ public:
m_MountingOrientation = Orientation;
}
+ struct SynthesizerAttributeEntry
+ {
+ CSynthesizer::Attribute Attrib;
+ LONGLONG Info;
+ LONG PinId;
+ };
+
void
- SetSynthesizerAttribute( CSynthesizer::Attribute Attrib, LONGLONG Info, LONG PinId );
+ SetSynthesizerAttributeList(
+ _In_ size_t Count,
+ _In_ SynthesizerAttributeEntry AttributeList[]
+ );
protected:
LONG
@@ -554,6 +564,7 @@ public:
DECLARE_PROPERTY( CExtendedProperty, TriggerTime );
DECLARE_PROPERTY( CExtendedProperty, TorchMode );
+ DECLARE_PROPERTY( CExtendedVidProcSetting, IRTorch );
DECLARE_PROPERTY_ASYNC( CExtendedVidProcSetting, Focus );
DECLARE_PROPERTY_ASYNC( CExtendedProperty, Iso );
@@ -576,6 +587,7 @@ public:
DECLARE_PROPERTY( CExtendedProperty, AdvancedPhoto );
DECLARE_PROPERTY( CExtendedVidProcSetting, FaceDetection );
DECLARE_PROPERTY( CExtendedProperty, VideoTemporalDenoising);
+ DECLARE_PROPERTY( CExtendedProperty, RelativePanel);
DECLARE_PROPERTY_VARSIZE_ASYNC( CRoiProperty, Roi );
diff --git a/avstream/avscamera/sys/SensorSimulation.cpp b/avstream/avscamera/sys/SensorSimulation.cpp
index 6ecd9007..e60372c1 100644
--- a/avstream/avscamera/sys/SensorSimulation.cpp
+++ b/avstream/avscamera/sys/SensorSimulation.cpp
@@ -331,6 +331,15 @@ Return Value:
}
m_TorchMode.Flags = KSCAMERA_EXTENDEDPROP_VIDEOTORCH_OFF;
m_TorchMode = 50UL;
+ m_IRTorch.Flags = KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALWAYS_ON;
+ m_IRTorch.Capability =
+ KSCAMERA_EXTENDEDPROP_IRTORCHMODE_OFF |
+ KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALWAYS_ON |
+ KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALTERNATING_FRAME_ILLUMINATION;
+ m_IRTorch = 100UL;
+ m_IRTorch.Min() = 20;
+ m_IRTorch.Max() = 100;
+ m_IRTorch.Step() = 5;
m_OptimizationHint.Flags = KSCAMERA_EXTENDEDPROP_OPTIMIZATION_PHOTO;
@@ -471,6 +480,14 @@ Return Value:
m_PowerLineFreq.Value = POWERLINEFREQ_DEFAULT;
m_PowerLineFreq.Flags = KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL;
+ // Set up our relative panel.
+ m_RelativePanel.Capability =
+ KSCAMERA_EXTENDEDPROP_RELATIVEPANELOPTIMIZATION_ON |
+ KSCAMERA_EXTENDEDPROP_RELATIVEPANELOPTIMIZATION_OFF |
+ KSCAMERA_EXTENDEDPROP_RELATIVEPANELOPTIMIZATION_DYNAMIC;
+ m_RelativePanel.Flags = KSCAMERA_EXTENDEDPROP_RELATIVEPANELOPTIMIZATION_OFF;
+ m_RelativePanel = (ULONG)AcpiPldPanelUnknown;
+
m_IsoResult = STATUS_SUCCESS;
m_EvCompResult = STATUS_SUCCESS;
m_WhiteBalanceResult= STATUS_SUCCESS;
@@ -1791,6 +1808,40 @@ SetOpticalImageStabilization(
return STATUS_SUCCESS;
}
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_RELATIVEPANEL.
+NTSTATUS
+CSensorSimulation::
+GetRelativePanel(
+ _Inout_ CExtendedProperty *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ *pProperty = m_RelativePanel;
+ pProperty->Flags = m_RelativePanel.Flags;
+ pProperty->Capability = KSCAMERA_EXTENDEDPROP_RELATIVEPANELOPTIMIZATION_ON |
+ KSCAMERA_EXTENDEDPROP_RELATIVEPANELOPTIMIZATION_OFF |
+ KSCAMERA_EXTENDEDPROP_RELATIVEPANELOPTIMIZATION_DYNAMIC;
+
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_RELATIVEPANEL.
+NTSTATUS
+CSensorSimulation::
+SetRelativePanel(
+ _In_ CExtendedProperty *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ m_RelativePanel = *pProperty;
+ m_RelativePanel.Flags = pProperty->Flags;
+ return STATUS_SUCCESS;
+}
+
// Get KSPROPERTY_CAMERACONTROL_EXTENDED_VIDEOTEMPORALDENOISING.
NTSTATUS
CSensorSimulation::
@@ -3024,6 +3075,37 @@ SetTorchMode(
return STATUS_SUCCESS;
}
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_IRTORCHMODE
+NTSTATUS
+CSensorSimulation::
+GetIRTorch(
+ _Inout_ CExtendedVidProcSetting *pTorch
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ *pTorch = m_IRTorch;
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_IRTORCHMODE
+NTSTATUS
+CSensorSimulation::
+SetIRTorch(
+ _In_ CExtendedVidProcSetting *pTorch
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ // Only overwrite the IR Torch Flags and value.
+ m_IRTorch.Flags = pTorch->Flags;
+ m_IRTorch = pTorch->GetULONG();
+
+ return STATUS_SUCCESS;
+}
+
// Get KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOMODE
NTSTATUS
CSensorSimulation::
diff --git a/avstream/avscamera/sys/SensorSimulation.h b/avstream/avscamera/sys/SensorSimulation.h
index a2dd1fe7..6124762c 100644
--- a/avstream/avscamera/sys/SensorSimulation.h
+++ b/avstream/avscamera/sys/SensorSimulation.h
@@ -50,6 +50,7 @@ protected:
ULONG m_FaceDetectionCurrentMax;
ULONGLONG m_SceneMode;
CExtendedProperty m_TorchMode;
+ CExtendedVidProcSetting m_IRTorch;
CExtendedProperty m_OptimizationHint;
CExtendedMetadata *m_MetadataInfo;
PKSCAMERA_PERFRAMESETTING_HEADER m_pPerFrameSettings;
@@ -61,7 +62,8 @@ protected:
ULONGLONG m_Histogram;
ULONGLONG m_OpticalImageStabilization;
ULONGLONG m_VideoTemporalDenoising;
- CExtendedProperty m_AdvancedPhoto;
+ CExtendedProperty m_RelativePanel;
+ CExtendedProperty m_AdvancedPhoto;
CWhiteBalanceRoiIspControl m_RoiWhiteBalance;
CExposureRoiIspControl m_RoiExposureMode;
@@ -207,6 +209,7 @@ public:
DECLARE_PROPERTY_GET( KSPROPERTY_CAMERACONTROL_IMAGE_PIN_CAPABILITY_S, PinDependence );
DECLARE_PROPERTY( CExtendedProperty, TriggerTime );
DECLARE_PROPERTY( CExtendedProperty, TorchMode );
+ DECLARE_PROPERTY( CExtendedVidProcSetting, IRTorch );
DECLARE_PROPERTY( CExtendedProperty, ExtendedFlash );
@@ -236,6 +239,7 @@ public:
DECLARE_PROPERTY_GET( CExtendedFieldOfView, FieldOfView );
DECLARE_PROPERTY_GET( CExtendedCameraAngleOffset, CameraAngleOffset );
DECLARE_PROPERTY( CExtendedProperty, VideoTemporalDenoising);
+ DECLARE_PROPERTY( CExtendedProperty, RelativePanel);
DECLARE_PROPERTY_VARSIZE_ASYNC_NOCANCEL( CRoiProperty, Roi );
@@ -288,4 +292,4 @@ const LONG WHITEBALANCE_DEF = 5000;
const LONG EXPOSURE_BILOG_MIN = -10;
const LONG EXPOSURE_BILOG_MAX = 9;
const LONG EXPOSURE_BILOG_STEP = 1;
-const LONG EXPOSURE_BILOG_DEF = -5; \ No newline at end of file
+const LONG EXPOSURE_BILOG_DEF = -5;
diff --git a/avstream/avscamera/sys/VideoHwSim.cpp b/avstream/avscamera/sys/VideoHwSim.cpp
index 33b6de90..839af530 100644
--- a/avstream/avscamera/sys/VideoHwSim.cpp
+++ b/avstream/avscamera/sys/VideoHwSim.cpp
@@ -27,6 +27,7 @@ CVideoHardwareSimulation::CVideoHardwareSimulation(
_In_ LONG PinID
)
: CHardwareSimulation( Sensor, PinID )
+ , m_Illuminated(FALSE)
{}
@@ -50,6 +51,54 @@ EmitMetadata(
if (0 != (pStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_METADATA))
{
+ PKS_FRAME_INFO pFrameInfo = (PKS_FRAME_INFO)(pStreamHeader + 1);
+ PKSSTREAM_METADATA_INFO pMetadata = (PKSSTREAM_METADATA_INFO)(pFrameInfo + 1);
+ ULONG BytesLeft = pMetadata->BufferSize - pMetadata->UsedSize;
+
+ // TODO: This metadata should only be exposed on a sensor category preview pin.
+ // It's possible I should derive a new preview sim to handle this; but for now
+ // we just populate the IR illumination state on every preview pin. Hopefully
+ // the app is smart enough to realize that this is meaningless if they have not
+ // selected an IR mediatype.
+ if (BytesLeft >= sizeof(KSCAMERA_METADATA_FRAMEILLUMINATION))
+ {
+ PKSCAMERA_METADATA_FRAMEILLUMINATION pPreviewIllumination =
+ (PKSCAMERA_METADATA_FRAMEILLUMINATION)(((PBYTE)pMetadata->SystemVa) + pMetadata->UsedSize);
+ RtlZeroMemory(pPreviewIllumination, sizeof(KSCAMERA_METADATA_FRAMEILLUMINATION));
+
+ pPreviewIllumination->Header.MetadataId = (ULONG)MetadataId_FrameIllumination;
+ pPreviewIllumination->Header.Size = sizeof(KSCAMERA_METADATA_FRAMEILLUMINATION);
+
+ // Toggle the Illumination state for an IR frame.
+ CExtendedVidProcSetting State;
+ (void)m_Sensor->GetIRTorch(&State);
+
+ if (State.Flags & KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALWAYS_ON)
+ {
+ m_Illuminated = TRUE;
+ pPreviewIllumination->Flags = KSCAMERA_METADATA_FRAMEILLUMINATION_FLAG_ON;
+ }
+ else if ((State.Flags & KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALTERNATING_FRAME_ILLUMINATION))
+ {
+ m_Illuminated = !m_Illuminated;
+ if (m_Illuminated)
+ {
+ pPreviewIllumination->Flags = KSCAMERA_METADATA_FRAMEILLUMINATION_FLAG_ON;
+ }
+ }
+ else
+ {
+ m_Illuminated = FALSE;
+ }
+
+ DBG_TRACE("Frame Illumination: Flags=0x%016llX, State=%s",
+ State.Flags,
+ (pPreviewIllumination->Flags == KSCAMERA_METADATA_FRAMEILLUMINATION_FLAG_ON ? "ON" : "OFF"));
+
+ pMetadata->UsedSize += sizeof(KSCAMERA_METADATA_FRAMEILLUMINATION);
+ BytesLeft -= sizeof(KSCAMERA_METADATA_FRAMEILLUMINATION);
+ }
+
CExtendedVidProcSetting FaceDetect;
m_Sensor->GetFaceDetection(&FaceDetect);
diff --git a/avstream/avscamera/sys/VideoHwSim.h b/avstream/avscamera/sys/VideoHwSim.h
index 40b0b24b..a576d9a1 100644
--- a/avstream/avscamera/sys/VideoHwSim.h
+++ b/avstream/avscamera/sys/VideoHwSim.h
@@ -38,5 +38,9 @@ public:
EmitMetadata(
_Inout_ PKSSTREAM_HEADER pStreamHeader
);
+
+private:
+ BOOLEAN m_Illuminated;
+
};
diff --git a/avstream/avscamera/sys/avscamera.inf b/avstream/avscamera/sys/avscamera.inx
index 2a17a764..f6f1e846 100644
--- a/avstream/avscamera/sys/avscamera.inf
+++ b/avstream/avscamera/sys/avscamera.inx
Binary files differ
diff --git a/avstream/avscamera/sys/filter.cpp b/avstream/avscamera/sys/filter.cpp
index 2680f503..dfb6ce1f 100644
--- a/avstream/avscamera/sys/filter.cpp
+++ b/avstream/avscamera/sys/filter.cpp
@@ -64,6 +64,7 @@ Return Value:
m_pCaptureDevice(NULL),
m_pPerFrameSettings(nullptr),
m_pinArray(nullptr),
+ m_pMinimumRequestedFrames(nullptr),
m_PhotoModeNotifier( Filter, &KSEVENTSETID_ExtendedCameraControl, KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOMODE ),
m_PhotoMaxFrameRateNotifier( Filter, &KSEVENTSETID_ExtendedCameraControl, KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOMAXFRAMERATE) ,
m_FocusNotifier( Filter, &KSEVENTSETID_ExtendedCameraControl, KSPROPERTY_CAMERACONTROL_EXTENDED_FOCUSMODE ),
@@ -141,10 +142,12 @@ Return Value:
IFFAILED_EXIT( m_Sensor->AddFilter(m_pKSFilter) );
IFNULL_EXIT(m_pinArray = new (PagedPool, 'sniP') CCapturePin *[m_Sensor->GetPinCount()]);
+ IFNULL_EXIT(m_pMinimumRequestedFrames = new (PagedPool, 'sniP') ULONG[m_Sensor->GetPinCount()]);
for( ULONG i=0; i<m_Sensor->GetPinCount(); i++ )
{
m_pinArray[i] = nullptr;
+ m_pMinimumRequestedFrames[i] = IMAGE_CAPTURE_PIN_MINIMUM_FRAMES;
}
done:
@@ -209,6 +212,7 @@ CCaptureFilter::~CCaptureFilter()
// may need to have some things reset.
m_Sensor->Reset();
+ delete [] m_pMinimumRequestedFrames;
delete [] m_pinArray;
DBG_LEAVE("(%S)", Name);
@@ -352,6 +356,11 @@ Return Value:
// Take out a weak reference to the pin object.
m_pinArray[Id] = pPin;
+ if (m_pinArray[Id] != nullptr)
+ {
+ m_pinArray[Id]->SetDesiredFrames(m_pMinimumRequestedFrames[Id]);
+ (void)m_pinArray[Id]->UpdateAllocatorFraming();
+ }
}
CCapturePin *
@@ -391,7 +400,8 @@ Return Value:
NTSTATUS
CCaptureFilter::
UpdateAllocatorFraming(
- _In_ ULONG PinId
+ _In_ ULONG PinId,
+ _In_ ULONG DesiredFrames
)
/*++
@@ -412,15 +422,20 @@ Return Value:
{
PAGED_CODE();
- NTSTATUS Status = STATUS_INVALID_PARAMETER;
+ NTSTATUS Status = STATUS_SUCCESS;
// Acquire the lock and update the Pin's allocator framing.
LockFilter Lock(m_pKSFilter);
if( m_pinArray[PinId] )
{
+ m_pinArray[PinId]->SetDesiredFrames(DesiredFrames);
Status = m_pinArray[PinId]->UpdateAllocatorFraming();
}
+ else
+ {
+ m_pMinimumRequestedFrames[PinId] = DesiredFrames;
+ }
DBG_LEAVE("()=0x%08X",Status);
return Status;
@@ -636,6 +651,7 @@ SetPhotoMode(
PAGED_CODE();
NTSTATUS Status = STATUS_INVALID_PARAMETER;
+ ULONG TotalFrames = IMAGE_CAPTURE_PIN_MINIMUM_FRAMES;
DBG_ENTER( "()" );
@@ -645,10 +661,6 @@ SetPhotoMode(
{
CExtendedPhotoMode Caps(*pMode);
Status = m_Sensor->GetPhotoMode( &Caps );
- CCapturePin *pPin = getPin(pMode->PinId);
-
- // Should always be valid.
- NT_ASSERT(pPin);
if( NT_SUCCESS(Status) )
{
@@ -686,7 +698,7 @@ SetPhotoMode(
// Assume the normal photo sequence case.
// For normal photo sequence, we provide history frames +1 or at least a minimum of 3 frames.
- ULONG TotalFrames = pMode->RequestedHistoryFrames() + 1;
+ TotalFrames = pMode->RequestedHistoryFrames() + 1;
// Modify TotalFrames for the VPS case.
// For VPS, we need LoopCount * FrameCount; but limit by the minimum(3) and maximum (20) frames.
@@ -708,14 +720,12 @@ SetPhotoMode(
DBG_TRACE( "Advertising Framing requirement: %d", TotalFrames );
- pPin->SetDesiredFrames(TotalFrames);
Status = STATUS_SUCCESS;
break;
}
case KSCAMERA_EXTENDEDPROP_PHOTOMODE_NORMAL:
{
// Set it back to the minimum number of frames.
- pPin->SetDesiredFrames(IMAGE_CAPTURE_PIN_MINIMUM_FRAMES);
Status = STATUS_SUCCESS;
break;
}
@@ -724,7 +734,7 @@ SetPhotoMode(
// Update allocator framing.
if( NT_SUCCESS( Status ) )
{
- Status = UpdateAllocatorFraming( pMode->PinId );
+ Status = UpdateAllocatorFraming( pMode->PinId, TotalFrames );
}
// Update the sensor object...
@@ -1118,13 +1128,13 @@ GetTorchMode(
NTSTATUS Status = STATUS_INVALID_PARAMETER;
- if( pTorchMode->isValid() &&
- pTorchMode->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE )
+ if (pTorchMode->isValid() &&
+ pTorchMode->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE)
{
- Status = m_Sensor->GetTorchMode( pTorchMode );
+ Status = m_Sensor->GetTorchMode(pTorchMode);
}
DBG_LEAVE("(PinId=%d, Flags=0x%016llX, Cap=0x%016llX)=0x%08X",
- pTorchMode->PinId, pTorchMode->Flags, pTorchMode->Capability, Status );
+ pTorchMode->PinId, pTorchMode->Flags, pTorchMode->Capability, Status);
return Status;
}
@@ -1139,34 +1149,101 @@ SetTorchMode(
NTSTATUS Status = STATUS_INVALID_PARAMETER;
- if( !(pTorchMode->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) &&
- pTorchMode->isValid() &&
- pTorchMode->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE &&
- pTorchMode->m_Value.Value.ul <= 100 )
+ if (!(pTorchMode->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) &&
+ pTorchMode->isValid() &&
+ pTorchMode->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE &&
+ pTorchMode->m_Value.Value.ul <= 100)
{
CExtendedProperty Caps(*pTorchMode);
Status = m_Sensor->GetTorchMode(&Caps);
- if( NT_SUCCESS(Status) )
+ if (NT_SUCCESS(Status))
{
// Assume an invalid parameter.
Status = STATUS_INVALID_PARAMETER;
- if( pTorchMode->Flags == (pTorchMode->Flags & Caps.Capability) )
+ if (pTorchMode->Flags == (pTorchMode->Flags & Caps.Capability))
{
- switch( pTorchMode->Flags )
+ switch (pTorchMode->Flags)
{
case KSCAMERA_EXTENDEDPROP_VIDEOTORCH_OFF:
case KSCAMERA_EXTENDEDPROP_VIDEOTORCH_ON:
case KSCAMERA_EXTENDEDPROP_VIDEOTORCH_ON_ADJUSTABLEPOWER:
- Status = m_Sensor->SetTorchMode( pTorchMode );
+ Status = m_Sensor->SetTorchMode(pTorchMode);
break;
}
}
}
}
DBG_LEAVE("(PinId=%d, Flags=0x%016llX, Cap=0x%016llX)=0x%08X",
- pTorchMode->PinId, pTorchMode->Flags, pTorchMode->Capability, Status );
+ pTorchMode->PinId, pTorchMode->Flags, pTorchMode->Capability, Status);
+ return Status;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_IRTORCHMODE
+NTSTATUS
+CCaptureFilter::
+GetIRTorch(
+ _Inout_ CExtendedVidProcSetting *pTorch
+)
+{
+ PAGED_CODE();
+
+ NTSTATUS Status = STATUS_INVALID_PARAMETER;
+
+ if (pTorch->isValid() &&
+ pTorch->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE)
+ {
+ Status = m_Sensor->GetIRTorch(pTorch);
+ }
+ DBG_LEAVE("(PinId=%d, Flags=0x%016llX, Cap=0x%016llX)=0x%08X",
+ pTorch->PinId, pTorch->Flags, pTorch->Capability, Status);
+ return Status;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_IRTORCHMODE
+NTSTATUS
+CCaptureFilter::
+SetIRTorch(
+ _In_ CExtendedVidProcSetting *pTorch
+)
+{
+ PAGED_CODE();
+
+ NTSTATUS Status = STATUS_INVALID_PARAMETER;
+
+ if (!(pTorch->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) &&
+ pTorch->isValid() &&
+ pTorch->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE)
+ {
+ CExtendedVidProcSetting Caps(*pTorch);
+ Status = m_Sensor->GetIRTorch(&Caps);
+
+ if (NT_SUCCESS(Status))
+ {
+ Status = Caps.BoundsCheck(pTorch->GetULONG());
+
+ if (NT_SUCCESS(Status))
+ {
+ // Assume an invalid parameter.
+ Status = STATUS_INVALID_PARAMETER;
+
+ if (pTorch->Flags == (pTorch->Flags & Caps.Capability))
+ {
+ switch (pTorch->Flags)
+ {
+ case KSCAMERA_EXTENDEDPROP_IRTORCHMODE_OFF:
+ case KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALWAYS_ON:
+ case KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALTERNATING_FRAME_ILLUMINATION:
+ Status = m_Sensor->SetIRTorch(pTorch);
+ break;
+ }
+ }
+ }
+ }
+ }
+ DBG_LEAVE("(PinId=%d, Flags=0x%016llX, Cap=0x%016llX)=0x%08X",
+ pTorch->PinId, pTorch->Flags, pTorch->Capability, Status);
return Status;
}
@@ -3494,6 +3571,66 @@ SetOpticalImageStabilization(
return Status;
}
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_RELATIVEPANEL.
+NTSTATUS
+CCaptureFilter::
+GetRelativePanel(
+ _Inout_ CExtendedProperty *pRelativePanel
+)
+{
+ PAGED_CODE();
+ NTSTATUS Status = STATUS_INVALID_PARAMETER;
+
+ if (pRelativePanel->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE &&
+ pRelativePanel->isValid())
+ {
+ //Get the current state
+ Status = m_Sensor->GetRelativePanel(pRelativePanel);
+ }
+
+ DBG_TRACE("pRelativePanel = %p, PinId = %u, Flags = %llu, Version = %u",
+ pRelativePanel, pRelativePanel->PinId, pRelativePanel->Flags, pRelativePanel->Version);
+
+ return Status;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_RELATIVEPANEL.
+NTSTATUS
+CCaptureFilter::
+SetRelativePanel(
+ _In_ CExtendedProperty *pRelativePanel
+)
+{
+ PAGED_CODE();
+
+ NTSTATUS Status = STATUS_INVALID_PARAMETER;
+
+ // Call must be Filter and flags must be supported and version must be 1
+ if (pRelativePanel->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE &&
+ pRelativePanel->isValid() &&
+ (KSCAMERA_EXTENDEDPROP_RELATIVEPANELOPTIMIZATION_ON == pRelativePanel->Flags ||
+ KSCAMERA_EXTENDEDPROP_RELATIVEPANELOPTIMIZATION_OFF == pRelativePanel->Flags))
+ {
+ CExtendedProperty Caps(*pRelativePanel);
+ Status = m_Sensor->GetRelativePanel(&Caps);
+
+ if (NT_SUCCESS(Status))
+ {
+ // Assume an invalid parameter.
+ Status = STATUS_INVALID_PARAMETER;
+
+ if (pRelativePanel->Flags == (pRelativePanel->Flags & Caps.Capability))
+ {
+ Status = m_Sensor->SetRelativePanel(pRelativePanel);
+ }
+ }
+ }
+ DBG_TRACE("pOIS = %p, PinId = %u, Flags = %llu, Version = %u",
+ pRelativePanel, pRelativePanel->PinId, pRelativePanel->Flags, pRelativePanel->Version);
+
+ return Status;
+}
+
// Get KSPROPERTY_CAMERACONTROL_EXTENDED_ADVANCEDPHOTO.
NTSTATUS
CCaptureFilter::
diff --git a/avstream/avscamera/sys/filter.h b/avstream/avscamera/sys/filter.h
index 292a6bc7..5b272a9d 100644
--- a/avstream/avscamera/sys/filter.h
+++ b/avstream/avscamera/sys/filter.h
@@ -58,6 +58,7 @@ private:
// The AVStream filter object associated with this CCaptureFilter.
//
CCapturePin **m_pinArray;
+ ULONG *m_pMinimumRequestedFrames;
protected:
//
@@ -331,7 +332,9 @@ DECLARE_PROPERTY_SET_HANDLER( type, name )
DECLARE_PROPERTY_HANDLERS( CExtendedProperty, Thumbnail )
DECLARE_PROPERTY_HANDLERS( CExtendedProperty, TriggerTime )
DECLARE_PROPERTY_HANDLERS( CExtendedProperty, TorchMode )
+ DECLARE_PROPERTY_HANDLERS( CExtendedVidProcSetting, IRTorch )
DECLARE_PROPERTY_HANDLERS( CExtendedProperty, VideoTemporalDenoising)
+ DECLARE_PROPERTY_HANDLERS( CExtendedProperty, RelativePanel)
DECLARE_PROPERTY_HANDLERS( KSPROPERTY_CAMERACONTROL_VIDEOSTABILIZATION_MODE_S, VideoStabMode )
DECLARE_PROPERTY_HANDLERS( KSPROPERTY_CAMERACONTROL_FLASH_S, Flash )
@@ -385,7 +388,7 @@ DECLARE_PROPERTY_SET_HANDLER( type, name )
// Make sure the PERFRAMESETTINGs passed to us are valid.
_Success_(return == 0)
NTSTATUS
- CCaptureFilter::ParsePFSBuffer(
+ ParsePFSBuffer(
_In_reads_bytes_(BufferLimit)
PKSCAMERA_PERFRAMESETTING_HEADER pPFS,
_In_ ULONG BufferLimit,
@@ -434,7 +437,8 @@ DECLARE_PROPERTY_SET_HANDLER( type, name )
// Update the pin's allocator to a specific frame count.
NTSTATUS
UpdateAllocatorFraming(
- _In_ ULONG PinId
+ _In_ ULONG PinId,
+ _In_ ULONG DesiredFrames
);
private:
diff --git a/avstream/avscamera/sys/hwsim.cpp b/avstream/avscamera/sys/hwsim.cpp
index 5322cff3..fdf7b367 100644
--- a/avstream/avscamera/sys/hwsim.cpp
+++ b/avstream/avscamera/sys/hwsim.cpp
@@ -1207,7 +1207,7 @@ Return Value:
{
PAGED_CODE();
- KScopedMutex Lock( m_ListLock );
+ KScopedMutex Lock(m_ListLock);
m_InterruptTime++;
@@ -1218,10 +1218,10 @@ Return Value:
//
if (m_PinState == PinRunning)
{
- LONGLONG Qpc = (LONGLONG) ConvertQPCtoTimeStamp(nullptr);
+ LONGLONG Qpc = (LONGLONG)ConvertQPCtoTimeStamp(nullptr);
LARGE_INTEGER Now;
- KeQuerySystemTimePrecise( &Now );
+ KeQuerySystemTimePrecise(&Now);
//
// Generate a "time stamp" just to overlay it onto the capture image.
// It makes it more exciting than bars that do nothing.
@@ -1230,12 +1230,16 @@ Return Value:
// the most recent streaming pin's index.
if (!m_Sensor->IsStillIndex(m_PinID))
{
+ CSensor::SynthesizerAttributeEntry AttributeList[] =
+ {
+ { CSynthesizer::FrameNumber, m_InterruptTime, m_PinID },
+ { CSynthesizer::RelativePts, (m_InterruptTime + 1) * m_TimePerFrame, m_PinID },
+ { CSynthesizer::QpcTime, Qpc, m_PinID }
+ };
DBG_TRACE("QPC=0x%016llX", Qpc);
// Broadcast the preview pin's info to all pin simulations.
- m_Sensor->SetSynthesizerAttribute(CSynthesizer::FrameNumber, m_InterruptTime, m_PinID);
- m_Sensor->SetSynthesizerAttribute(CSynthesizer::RelativePts, (m_InterruptTime + 1) * m_TimePerFrame, m_PinID);
- m_Sensor->SetSynthesizerAttribute(CSynthesizer::QpcTime, Qpc, m_PinID);
+ m_Sensor->SetSynthesizerAttributeList(SIZEOF_ARRAY(AttributeList), AttributeList);
}
m_Synthesizer->DoSynthesize();
@@ -1243,13 +1247,13 @@ Return Value:
CHAR Text[64];
CExtendedProperty Control;
- m_Sensor->GetVideoStabilization( &Control );
+ m_Sensor->GetVideoStabilization(&Control);
RtlStringCbPrintfA(Text, sizeof(Text), "DVS: %s", DVS_Text(Control.Flags));
- m_Synthesizer->OverlayText( 0, m_Height-38, 1, Text, TRANSPARENT, TEXT_COLOR );
+ m_Synthesizer->OverlayText(0, m_Height - 38, 1, Text, TRANSPARENT, TEXT_COLOR);
- m_Sensor->GetOpticalImageStabilization( &Control );
+ m_Sensor->GetOpticalImageStabilization(&Control);
RtlStringCbPrintfA(Text, sizeof(Text), "OIS: %s", OIS_Text(Control.Flags));
- m_Synthesizer->OverlayText( 0, m_Height-48, 1, Text, TRANSPARENT, TEXT_COLOR );
+ m_Synthesizer->OverlayText(0, m_Height - 48, 1, Text, TRANSPARENT, TEXT_COLOR);
//
// Add the Missed frame count
@@ -1257,7 +1261,7 @@ Return Value:
size_t len = 0;
RtlStringCchLengthA(Text, sizeof(Text), &len);
m_Synthesizer->OverlayText(
- (m_Width - (((ULONG)len*8))), // right-adjust text.
+ (m_Width - (((ULONG)len * 8))), // right-adjust text.
(m_Height - 48),
1,
Text,
@@ -1268,12 +1272,12 @@ Return Value:
//
// Add the estimated FPS
LONGLONG Target = NANOSECONDS / m_TimePerFrame;
- LONGLONG FPS = ((LONGLONG)m_InterruptTime * NANOSECONDS) / ( (Now.QuadPart - m_StartTime.QuadPart) + (NANOSECONDS/2) );
+ LONGLONG FPS = ((LONGLONG)m_InterruptTime * NANOSECONDS) / ((Now.QuadPart - m_StartTime.QuadPart) + (NANOSECONDS / 2));
RtlStringCbPrintfA(Text, sizeof(Text), "%lld/%lld FPS", FPS, Target);
len = 0;
RtlStringCchLengthA(Text, sizeof(Text), &len);
- m_Synthesizer->OverlayText (
- (m_Width - (((ULONG)len*8))), // right-adjust text.
+ m_Synthesizer->OverlayText(
+ (m_Width - (((ULONG)len * 8))), // right-adjust text.
(m_Height - 38),
1,
Text,
@@ -1284,7 +1288,7 @@ Return Value:
//
// Fill scatter gather buffers
//
- if (!NT_SUCCESS (FillScatterGatherBuffers ()))
+ if (!NT_SUCCESS(FillScatterGatherBuffers()))
{
m_NumFramesSkipped++;
}
@@ -1294,28 +1298,28 @@ Return Value:
// Issue an interrupt to our hardware sink. This is a "fake" interrupt.
// It will occur at DISPATCH_LEVEL.
//
- m_Sensor -> Interrupt (m_PinID);
+ m_Sensor->Interrupt(m_PinID);
//
// Schedule the timer for the next interrupt time, if the pin is still running.
//
- if( m_PinState == PinRunning )
+ if (m_PinState == PinRunning)
{
LARGE_INTEGER NextTime;
NextTime.QuadPart = m_StartTime.QuadPart +
- (m_TimePerFrame * (m_InterruptTime + 1));
+ (m_TimePerFrame * (m_InterruptTime + 1));
#ifdef ENABLE_TRACING // To keep us from a tight spin when trying to debug this code...
LARGE_INTEGER Now;
KeQuerySystemTime(&Now);
- if( Now.QuadPart >= NextTime.QuadPart )
+ if (Now.QuadPart >= NextTime.QuadPart)
{
- NextTime.QuadPart = 0LL - m_TimePerFrame ;
+ NextTime.QuadPart = 0LL - m_TimePerFrame;
}
#endif
- m_IsrTimer.Set( NextTime );
+ m_IsrTimer.Set(NextTime);
}
}
diff --git a/avstream/avscamera/sys/imagecapture.cpp b/avstream/avscamera/sys/imagecapture.cpp
index 06d334d3..7ba53fa4 100644
--- a/avstream/avscamera/sys/imagecapture.cpp
+++ b/avstream/avscamera/sys/imagecapture.cpp
@@ -121,9 +121,11 @@ Close(
{
PAGED_CODE();
+ // Reset the image sim's counts and queues.
Reset();
- return STATUS_SUCCESS;
+ // Call the base Close operation.
+ return CCapturePin::Close(Irp);
}
// ImageCapturePinDispatch:
diff --git a/avstream/avshws/README.md b/avstream/avshws/README.md
index 49bb9e04..9a222462 100644
--- a/avstream/avshws/README.md
+++ b/avstream/avshws/README.md
@@ -84,3 +84,14 @@ In the upper-left corner of the image, a counter counts the number of frames tha
| --- | --- |
| Avshws.h | Main header file for the sample |
| Avshws.inf | Sample installation file |
+Capture.cpp | Capture pin implementation for all capture pins on the sample filter.
+Capture.h | Capture pin level header for all capture pins on the sample filter.
+Device.cpp | Device level implementation of the simulated hardware.
+Device.h | Device level header for the simulated hardware.
+Filter.cpp | Capture filter implementation (including frame synthesis) for the fake capture filter.
+Filter.h | Filter level header for the filter-centric capture filter.
+HWSim.cpp | Hardware simulation implementation, including fake "DMA" transfers, scatter gather mapping handling, ISRs, etc.
+HWSim.h | Hardware simulation header.
+Image.cpp | Image synthesis and overlay code. These objects provide image synthesis (pixel, color-bar, etc) onto RGB24 and UYVY buffers as well as software string overlay into these buffers.
+Image.h | Image synthesis and overlay header.
+Purecall.h | _purecall stub necessary for virtual function usage in drivers.
diff --git a/avstream/avshws/avshws.inf b/avstream/avshws/avshws.inf
deleted file mode 100644
index 9bbbc42a..00000000
--- a/avstream/avshws/avshws.inf
+++ /dev/null
@@ -1,173 +0,0 @@
-;/*++
-;
-;Copyright (c) Microsoft Corporation. All rights reserved.
-;
-; THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
-; KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-; IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
-; PURPOSE.
-;
-;Module Name:
-;
-; AVSHWS.INF
-;
-;Abstract:
-;
-;
-;AVStream pin centric sample mini driver (AVSHWS.sys) installation file.
-;Supports x86, amd64, arm and arm64 platforms
-;
-;--*/
-
-[Version]
-signature="$WINDOWS NT$"
-Class=Camera
-ClassGuid={ca3e7ab9-b4c3-4ae6-8251-579ef933890f}
-Provider=%ProviderName%
-Catalogfile=avshws.cat
-DriverVer=08/31/2006,6.0.5600.0
-
-[SourceDisksNames]
-1000=%cdname%,,,
-
-[SourceDisksFiles]
-avshws.sys=1000
-
-[DestinationDirs]
-DefaultDestDir=12
-avshws.CopyFiles=12
-
-[avshws.CopyFiles]
-avshws.sys
-
-[Manufacturer]
-%ManufacturerName%=Standard,NTx86,NTamd64,ntarm,ntarm64
-
-[Standard.NTx86]
-%avshws.DeviceDesc%=avshws.NTx86,AVSHWS
-
-[Standard.NTamd64]
-%avshws.DeviceDesc%=avshws.NTamd64,AVSHWS
-
-[Standard.NTarm]
-%avshws.DeviceDesc%=avshws.NTarm,AVSHWS
-
-[Standard.NTarm64]
-%avshws.DeviceDesc%=avshws.NTarm64,AVSHWS
-
-;---------------------------------------------------------------
-; x 86 D D I n s t a l l
-;---------------------------------------------------------------
-
-[avshws.NTx86]
-Include=ks.inf, KSCAPTUR.inf
-Needs=KS.Registration,KSCAPTUR.Registration.NT
-CopyFiles=avshws.CopyFiles
-
-;---------------------------------------------------------------
-; A M D 64 D D I n s t a l l
-;---------------------------------------------------------------
-
-[avshws.NTamd64]
-Include=ks.inf,KSCAPTUR.inf
-Needs=KS.Registration,KSCAPTUR.Registration.NT
-CopyFiles=avshws.CopyFiles
-
-;---------------------------------------------------------------
-; A R M D D I n s t a l l
-;---------------------------------------------------------------
-
-[avshws.NTarm]
-Include=ks.inf,KSCAPTUR.inf
-Needs=KS.Registration,KSCAPTUR.Registration.NT
-CopyFiles=avshws.CopyFiles
-
-;---------------------------------------------------------------
-; A R M 64 D D I n s t a l l
-;---------------------------------------------------------------
-
-[avshws.NTarm64]
-Include=ks.inf,KSCAPTUR.inf
-Needs=KS.Registration,KSCAPTUR.Registration.NT
-CopyFiles=avshws.CopyFiles
-
-;---------------------------------------------------------------
-; I n t e r f a c e s
-;---------------------------------------------------------------
-
-[avshws.NTx86.Interfaces]
-AddInterface=%KSCATEGORY_CAPTURE%,"GLOBAL",CaptureInterface.NT,0
-AddInterface=%KSCATEGORY_VIDEO%,"GLOBAL",CaptureInterface.NT,0
-AddInterface=%KSCATEGORY_VIDEO_CAMERA%,"GLOBAL",CaptureInterface.NT,0
-
-[avshws.NTamd64.Interfaces]
-AddInterface=%KSCATEGORY_CAPTURE%,"GLOBAL",CaptureInterface.NT,0
-AddInterface=%KSCATEGORY_VIDEO%,"GLOBAL",CaptureInterface.NT,0
-AddInterface=%KSCATEGORY_VIDEO_CAMERA%,"GLOBAL",CaptureInterface.NT,0
-
-[avshws.NTarm.Interfaces]
-AddInterface=%KSCATEGORY_CAPTURE%,"GLOBAL",CaptureInterface.NT,0
-AddInterface=%KSCATEGORY_VIDEO%,"GLOBAL",CaptureInterface.NT,0
-AddInterface=%KSCATEGORY_VIDEO_CAMERA%,"GLOBAL",CaptureInterface.NT,0
-
-[avshws.NTarm64.Interfaces]
-AddInterface=%KSCATEGORY_CAPTURE%,"GLOBAL",CaptureInterface.NT,0
-AddInterface=%KSCATEGORY_VIDEO%,"GLOBAL",CaptureInterface.NT,0
-AddInterface=%KSCATEGORY_VIDEO_CAMERA%,"GLOBAL",CaptureInterface.NT,0
-
-[CaptureInterface.NT]
-AddReg=avshws.Reader.AddReg
-
-;---------------------------------------------------------------
-; A d d R e g
-;---------------------------------------------------------------
-
-[avshws.Reader.AddReg]
-HKR,,CLSID,,%Proxy.CLSID%
-HKR,,FriendlyName,,%avshws.Reader.FriendlyName%
-
-;---------------------------------------------------------------
-; S e r v i c e s
-;---------------------------------------------------------------
-
-[avshws.NTx86.Services]
-AddService=avshws, 0x00000002, avshws.ServiceInstall
-
-[avshws.NTamd64.Services]
-AddService=avshws, 0x00000002, avshws.ServiceInstall
-
-[avshws.NTarm.Services]
-AddService=avshws, 0x00000002, avshws.ServiceInstall
-
-[avshws.NTarm64.Services]
-AddService=avshws, 0x00000002, avshws.ServiceInstall
-
-[avshws.ServiceInstall]
-DisplayName=%avshws.DeviceDesc%
-ServiceType=%SERVICE_KERNEL_DRIVER%
-StartType=%SERVICE_DEMAND_START%
-ErrorControl=%SERVICE_ERROR_NORMAL%
-ServiceBinary=%12%\avshws.sys
-
-;---------------------------------------------------------------
-; S t r i n g s
-;---------------------------------------------------------------
-
-[Strings]
-; non-localizable
-Proxy.CLSID="{17CCA71B-ECD7-11D0-B908-00A0C9223196}"
-KSCATEGORY_CAPTURE="{65E8773D-8F56-11D0-A3B9-00A0C9223196}"
-KSCATEGORY_VIDEO="{6994AD05-93EF-11D0-A3CC-00A0C9223196}"
-KSCATEGORY_VIDEO_CAMERA="{E5323777-F976-4f5b-9B55-B94699C46E44}"
-
-SERVICE_KERNEL_DRIVER=1
-SERVICE_DEMAND_START=3
-SERVICE_ERROR_NORMAL=1
-REG_DWORD=0x00010001
-
-;localizable
-ProviderName="TODO-Set-Provider"
-ManufacturerName="TODO-Set-Manufacturer"
-avshws.DeviceDesc="AVStream Simulated Hardware Sample"
-avshws.Reader.FriendlyName="avshws Source"
-cdname="AVSHWS Installation Disk" \ No newline at end of file
diff --git a/avstream/avshws/avshws.inx b/avstream/avshws/avshws.inx
new file mode 100644
index 00000000..ca763d0a
--- /dev/null
+++ b/avstream/avshws/avshws.inx
Binary files differ
diff --git a/avstream/avshws/avshws.sln b/avstream/avshws/avshws.sln
index 877a4ca9..ba4ee493 100644
--- a/avstream/avshws/avshws.sln
+++ b/avstream/avshws/avshws.sln
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.28307.136
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29519.181
MinimumVisualStudioVersion = 12.0
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "avshws", "avshws.vcxproj", "{77FA53EC-3637-411C-B708-C8EED64543A4}"
EndProject
@@ -45,4 +45,3 @@ Global
SolutionGuid = {5EBC439F-EC31-448F-B129-434D42485011}
EndGlobalSection
EndGlobal
- \ No newline at end of file
diff --git a/avstream/avshws/avshws.vcxproj b/avstream/avshws/avshws.vcxproj
index 115a05c9..7d9e015a 100644
--- a/avstream/avshws/avshws.vcxproj
+++ b/avstream/avshws/avshws.vcxproj
@@ -319,7 +319,7 @@
<ResourceCompile Include="avshws.rc" />
</ItemGroup>
<ItemGroup>
- <Inf Exclude="@(Inf)" Include="*.inf" />
+ <Inf Exclude="@(Inf)" Include="*.inf;*.inx" />
<FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
</ItemGroup>
<ItemGroup>
@@ -331,4 +331,4 @@
<ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-</Project> \ No newline at end of file
+</Project>
diff --git a/avstream/avshws/capture.cpp b/avstream/avshws/capture.cpp
index d68ce1da..13ddbfc0 100644
--- a/avstream/avshws/capture.cpp
+++ b/avstream/avshws/capture.cpp
@@ -265,7 +265,7 @@ Return Value:
VideoInfoHeader);
m_VideoInfoHeader = reinterpret_cast <PKS_VIDEOINFOHEADER> (
- ExAllocatePoolWithTag (
+ ExAllocatePoolZero (
NonPagedPoolNx,
KS_SIZE_VIDEOHEADER (ConnectionHeader),
AVSHWS_POOLTAG
diff --git a/avstream/avshws/device.cpp b/avstream/avshws/device.cpp
index 44fc9704..b0a7fb23 100644
--- a/avstream/avshws/device.cpp
+++ b/avstream/avshws/device.cpp
@@ -31,13 +31,7 @@ PVOID operator new
POOL_TYPE poolType
)
{
- PVOID result = ExAllocatePoolWithTag(poolType,iSize,'wNCK');
-
- if (result) {
- RtlZeroMemory(result,iSize);
- }
-
- return result;
+ return ExAllocatePoolZero(poolType,iSize,'wNCK');
}
PVOID operator new
@@ -50,13 +44,7 @@ PVOID operator new
ULONG tag
)
{
- PVOID result = ExAllocatePoolWithTag(poolType,iSize,tag);
-
- if (result) {
- RtlZeroMemory(result,iSize);
- }
-
- return result;
+ return ExAllocatePoolZero(poolType,iSize,tag);
}
PVOID
@@ -69,14 +57,7 @@ operator new[](
ULONG tag
)
{
- PVOID result = ExAllocatePoolWithTag(poolType, iSize, tag);
-
- if (result)
- {
- RtlZeroMemory(result, iSize);
- }
-
- return result;
+ return ExAllocatePoolWZero(poolType, iSize, tag);
}
/*++
diff --git a/avstream/avshws/hwsim.cpp b/avstream/avshws/hwsim.cpp
index 1e813bc2..46d6be62 100644
--- a/avstream/avshws/hwsim.cpp
+++ b/avstream/avshws/hwsim.cpp
@@ -219,7 +219,7 @@ Return Value:
// Allocate a scratch buffer for the synthesizer.
//
m_SynthesisBuffer = reinterpret_cast <PUCHAR> (
- ExAllocatePoolWithTag (
+ ExAllocatePoolZero (
NonPagedPoolNx,
m_ImageSize,
AVSHWS_POOLTAG
diff --git a/avstream/avshws/makefile b/avstream/avshws/makefile
new file mode 100644
index 00000000..e8428c0d
--- /dev/null
+++ b/avstream/avshws/makefile
@@ -0,0 +1,15 @@
+!IF 0
+
+Copyright (C) Microsoft Corporation, 1999 - 1999
+
+Module Name:
+
+ makefile.
+
+!ENDIF
+
+!if "$(DDK_TARGET_OS)"=="Win2K"
+!message This sample is not intended to target the Windows 2000 platform.
+!else
+!INCLUDE $(NTMAKEENV)\makefile.def
+!endif \ No newline at end of file
diff --git a/avstream/avssamp/Filter.cpp b/avstream/avssamp/Filter.cpp
index 524d6ad8..b3b70c30 100644
--- a/avstream/avssamp/Filter.cpp
+++ b/avstream/avssamp/Filter.cpp
@@ -268,17 +268,17 @@ Return Value:
//
PKSDATARANGE_AUDIO DataRangeAudio =
reinterpret_cast <PKSDATARANGE_AUDIO> (
- ExAllocatePoolWithTag (PagedPool, sizeof (KSDATARANGE_AUDIO), AVSSMP_POOLTAG)
+ ExAllocatePoolZero (PagedPool, sizeof (KSDATARANGE_AUDIO), AVSSMP_POOLTAG)
);
PKSDATARANGE_AUDIO *DataRanges =
reinterpret_cast <PKSDATARANGE_AUDIO *> (
- ExAllocatePoolWithTag (PagedPool, sizeof (PKSDATARANGE_AUDIO), AVSSMP_POOLTAG)
+ ExAllocatePoolZero (PagedPool, sizeof (PKSDATARANGE_AUDIO), AVSSMP_POOLTAG)
);
PKSALLOCATOR_FRAMING_EX Framing =
reinterpret_cast <PKSALLOCATOR_FRAMING_EX> (
- ExAllocatePoolWithTag (PagedPool, sizeof (KSALLOCATOR_FRAMING_EX), AVSSMP_POOLTAG)
+ ExAllocatePoolZero (PagedPool, sizeof (KSALLOCATOR_FRAMING_EX), AVSSMP_POOLTAG)
);
if (DataRangeAudio && DataRanges && Framing) {
diff --git a/avstream/avssamp/avssamp.cpp b/avstream/avssamp/avssamp.cpp
index 68741c9e..1ba03089 100644
--- a/avstream/avssamp/avssamp.cpp
+++ b/avstream/avssamp/avssamp.cpp
@@ -38,13 +38,7 @@ PVOID operator new
POOL_TYPE poolType
)
{
- PVOID result = ExAllocatePoolWithTag(poolType,iSize,'wNCK');
-
- if (result) {
- RtlZeroMemory(result,iSize);
- }
-
- return result;
+ return ExAllocatePoolZero(poolType,iSize,'wNCK');
}
PVOID operator new
@@ -57,13 +51,7 @@ PVOID operator new
ULONG tag
)
{
- PVOID result = ExAllocatePoolWithTag(poolType,iSize,tag);
-
- if (result) {
- RtlZeroMemory(result,iSize);
- }
-
- return result;
+ return ExAllocatePoolZero(poolType,iSize,tag);
}
/*++
diff --git a/avstream/avssamp/avssamp.inf b/avstream/avssamp/avssamp.inf
deleted file mode 100644
index 00003e78..00000000
--- a/avstream/avssamp/avssamp.inf
+++ /dev/null
@@ -1,93 +0,0 @@
-; Copyright (c) Microsoft Corporation. All rights reserved.
-;
-; avssamp.INF -- This file contains installation information for the filter-based
-; AVStream sample driver avssamp.sys
-;
-; Note:
-;
-; This INF expects the following hierarchy in the installation folder:
-;
-; \
-; avssamp.inf
-; avssamp.sys
-;
-
-[Version]
-Signature="$Windows NT$"
-Class=Camera
-ClassGuid={ca3e7ab9-b4c3-4ae6-8251-579ef933890f}
-Provider=%ProviderName%
-CatalogFile=avssamp.cat
-DriverVer=09/30/2004,1.0.0.0
-
-[SourceDisksNames]
-1000 = %cdname%,,,
-
-[SourceDisksFiles]
-avssamp.sys = 1000
-
-[ControlFlags]
-ExcludeFromSelect=*
-
-[DestinationDirs]
-avssamp.CopyFiles=12
-
-[Manufacturer]
-%ManufacturerName%=Standard,NTamd64,NTx86
-
-;---------------------------------------------------------------
-; The preferred method to install as a Root-enumerated device.
-; NOTE: DO NOT INCLUDE THIS FOR A HARDWARE DRIVER!
-;---------------------------------------------------------------
-
-[DeviceInstall32]
-AddDevice = ROOT\SW\{20698827-7099-4c4e-861A-4879D639A35F},,avssamp_RootEnumInstall
-
-[avssamp_RootEnumInstall]
-HardwareIds = SW\{20698827-7099-4c4e-861A-4879D639A35F}
-;---------------------------------------------------------------
-
-[Standard.NTx86]
-%avssamp.DeviceDesc%=avssamp,SW\{20698827-7099-4c4e-861A-4879D639A35F}
-
-[Standard.NTamd64]
-%avssamp.DeviceDesc%=avssamp,SW\{20698827-7099-4c4e-861A-4879D639A35F}
-
-[avssamp.NT]
-include=ks.inf,kscaptur.inf
-needs=KS.Registration,KSCAPTUR.Registration.NT
-CopyFiles=avssamp.CopyFiles
-
-[avssamp.CopyFiles]
-avssamp.sys
-
-[avssamp.NT.Services]
-AddService=avssamp, 0x00000002, avssamp.ServiceInstall
-
-[avssamp.ServiceInstall]
-DisplayName=%avssamp.DeviceDesc%
-ServiceType=%SERVICE_KERNEL_DRIVER%
-StartType=%SERVICE_DEMAND_START%
-ErrorControl=%SERVICE_ERROR_NORMAL%
-ServiceBinary=%12%\avssamp.sys
-
-[Strings]
-; non-localizable
-Proxy.CLSID="{17CCA71B-ECD7-11D0-B908-00A0C9223196}"
-avssamp.DeviceId="{20698827-7099-4c4e-861A-4879D639A35F}"
-KSCATEGORY_CAPTURE="{65E8773D-8F56-11D0-A3B9-00A0C9223196}"
-KSSTRING_Filter="{9B365890-165F-11D0-A195-0020AFD156E4}"
-
-SERVICE_KERNEL_DRIVER=1
-SERVICE_DEMAND_START=3
-SERVICE_ERROR_NORMAL=1
-REG_EXPAND_SZ=0x00020000
-REG_DWORD=0x00010001
-
-;localizable
-ProviderName="TODO-Set-Provider"
-ManufacturerName="TODO-Set-Manufacturer"
-avssamp.DeviceDesc="AVStream Filter-Centric Sample Driver"
-avssamp.Reader.FriendlyName="avssamp Source"
-
-cdname="Disk 1"
diff --git a/avstream/avssamp/avssamp.inx b/avstream/avssamp/avssamp.inx
new file mode 100644
index 00000000..bcb18baa
--- /dev/null
+++ b/avstream/avssamp/avssamp.inx
Binary files differ
diff --git a/avstream/avssamp/avssamp.vcxproj b/avstream/avssamp/avssamp.vcxproj
index 21c292d2..77567a8f 100644
--- a/avstream/avssamp/avssamp.vcxproj
+++ b/avstream/avssamp/avssamp.vcxproj
@@ -187,7 +187,7 @@
<ResourceCompile Include="avssamp.rc" />
</ItemGroup>
<ItemGroup>
- <Inf Exclude="@(Inf)" Include="*.inf" />
+ <Inf Exclude="@(Inf)" Include="*.inf;*.inx" />
<FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
</ItemGroup>
<ItemGroup>
diff --git a/avstream/avssamp/makefile b/avstream/avssamp/makefile
new file mode 100644
index 00000000..ab62d10e
--- /dev/null
+++ b/avstream/avssamp/makefile
@@ -0,0 +1,15 @@
+!IF 0
+
+Copyright (C) Microsoft Corporation, 1999 - 1999
+
+Module Name:
+
+ makefile.
+
+!ENDIF
+
+!if "$(DDK_TARGET_OS)"=="Win2K"
+!message This sample is not intended to target the Windows 2000 platform.
+!else
+!INCLUDE $(NTMAKEENV)\makefile.def
+!endif
diff --git a/avstream/avssamp/video.cpp b/avstream/avssamp/video.cpp
index d2291a24..1be9b56e 100644
--- a/avstream/avssamp/video.cpp
+++ b/avstream/avssamp/video.cpp
@@ -1,4 +1,4 @@
-/**************************************************************************
+/**************************************************************************
AVStream Filter-Centric Sample
@@ -23,7 +23,7 @@
/**************************************************************************
PAGEABLE CODE
-
+
**************************************************************************/
#ifdef ALLOC_PRAGMA
@@ -210,7 +210,7 @@ Return Value:
VideoInfoHeader);
m_VideoInfoHeader = reinterpret_cast <PKS_VIDEOINFOHEADER> (
- ExAllocatePoolWithTag (
+ ExAllocatePoolZero (
NonPagedPool,
KS_SIZE_VIDEOHEADER (ConnectionHeader),
AVSSMP_POOLTAG
@@ -557,7 +557,7 @@ Routine Description:
selected in order to change the format for the pin. In this case,
OldFormat will not be NULL.
- Validate that the format is acceptible and perform the actions necessary
+ Validate that the format is acceptable and perform the actions necessary
to change format if appropriate.
Arguments:
@@ -864,7 +864,7 @@ Return Value:
if (FromState == KSSTATE_STOP) {
m_SynthesisBuffer = reinterpret_cast <PUCHAR> (
- ExAllocatePoolWithTag (
+ ExAllocatePoolZero (
NonPagedPool,
m_VideoInfoHeader -> bmiHeader.biSizeImage,
AVSSMP_POOLTAG
diff --git a/avstream/avssamp/wave.cpp b/avstream/avssamp/wave.cpp
index 7af2f60a..de110e69 100644
--- a/avstream/avssamp/wave.cpp
+++ b/avstream/avssamp/wave.cpp
@@ -319,7 +319,7 @@ Return Value:
//
if (NT_SUCCESS (Status)) {
m_WaveData = reinterpret_cast <PUCHAR> (
- ExAllocatePoolWithTag (NonPagedPool, DataBlockSize, AVSSMP_POOLTAG)
+ ExAllocatePoolZero (NonPagedPool, DataBlockSize, AVSSMP_POOLTAG)
);
if (!m_WaveData) {
diff --git a/avstream/sampledevicemft/basepin.cpp b/avstream/sampledevicemft/basepin.cpp
index d4220397..563ff610 100644
--- a/avstream/sampledevicemft/basepin.cpp
+++ b/avstream/sampledevicemft/basepin.cpp
@@ -3,6 +3,7 @@
#include "multipinmft.h"
#include "multipinmfthelpers.h"
#include "basepin.h"
+#include "contosodevice.h"
#ifdef MF_WPP
#include "basepin.tmh" //--REF_ANALYZER_DONT_REMOVE--
@@ -323,7 +324,7 @@ STDMETHODIMP CInPin::WaitForSetInputPinMediaChange()
if ( dwWait != WAIT_OBJECT_0 )
{
- hr = E_FAIL;
+ hr = HRESULT_FROM_WIN32(GetLastError());
goto done;
}
done:
@@ -384,23 +385,79 @@ HRESULT CInPin::SetInputStreamState(
return hr;
}
-void CInPin::ReleaseConnectedPins()
+STDMETHODIMP_(VOID) CInPin::ShutdownPin()
{
m_spSourceTransform = nullptr;
m_outpin = nullptr;
}
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+//
+// ForwardSecureBuffer()
+//
+// Parameters:
+// sample - The sample to send out for secure processing
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+// This helper function calls back to the AVstream driver for post-processing of a
+// secure buffer. This is done here as an example for simplicity. A more realistic
+// scenario might have you calling into an ISP driver that is not an AVstream driver.
+// To do that you would need to acquire a handle to that device and post an IOCTL.
+// That device would in turn need to have a secure companion driver (trustlet)
+// installed as part of the package to process the buffer.
+//
+HRESULT CInPin::ForwardSecureBuffer(
+ _In_ IMFSample *sample
+)
+{
+ DWORD bytesReturned = 0;
+ CONTOSODEVICE_PROCESSBUFFER_PAYLOAD payload = { 0 };
+ KSPROPERTY property = { 0 };
+
+ wil::com_ptr_nothrow<IMFMediaBuffer> mediaBuffer;
+ wil::com_ptr_nothrow<IMFSecureBuffer> secureBuffer;
+
+ // Set up our private KSPROPERTY to some sample avstream driver.
+ property.Set = PROPSETID_CONTOSODEVICE;
+ property.Id = KSPROPERTY_CONTOSODEVICE_PROCESSBUFFER;
+ property.Flags = KSPROPERTY_TYPE_SET;
+ // Set up the payload for that property. Includes the secure buffer ID and buffer length.
+ RETURN_IF_FAILED(sample->GetBufferByIndex(0, &mediaBuffer));
+ // Forward the buffer if it is secure.
+ if (mediaBuffer.try_query_to(&secureBuffer))
+ {
+ RETURN_IF_FAILED(secureBuffer->GetIdentifier(&payload.identifier));
+ RETURN_IF_FAILED(mediaBuffer->GetMaxLength(&payload.size));
+
+ // Log the buffer's secure ID and size for debugging.
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! identifier=%!GUID!, length=%d", &payload.identifier, payload.size);
+
+ // Send the KSPROPERTY synchronously to the driver.
+ RETURN_IF_FAILED(KsProperty(&property, sizeof(property), &payload, sizeof(payload), &bytesReturned));
+ }
+ return S_OK;
+}
+#endif // ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
//
//Output Pin Implementation
//
COutPin::COutPin(
_In_ ULONG ulPinId,
_In_opt_ CMultipinMft *pparent,
- _In_ IKsControl* pIksControl
+ _In_ IKsControl* pIksControl
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ , _In_ MFSampleAllocatorUsage allocatorUsage
+#endif
)
- : CBasePin( ulPinId, pparent ),
- m_firstSample( false ),
- m_queue(nullptr)
+ : CBasePin(ulPinId, pparent)
+ , m_firstSample(false)
+ , m_queue(nullptr)
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ , m_allocatorUsage(allocatorUsage)
+#endif
{
HRESULT hr = S_OK;
ComPtr<IMFAttributes> spAttributes;
@@ -507,6 +564,14 @@ STDMETHODIMP_(VOID) COutPin::SetFirstSample(
m_firstSample = fisrtSample;
}
+STDMETHODIMP_(VOID) COutPin::SetAllocator(
+ _In_ IMFVideoSampleAllocator* pAllocator
+)
+{
+ CAutoLock Lock(lock());
+ m_spDefaultAllocator = pAllocator;
+}
+
/*++
COutPin::FlushQueues
Description:
@@ -524,7 +589,7 @@ HRESULT COutPin::FlushQueues()
/*++
COutPin::ChangeMediaTypeFromInpin
Description:
-called from the Device Transfrom When the input media type is changed. This will result in
+called from the Device Transform when the input media type is changed. This will result in
the xvp being possibly installed in the queue if the media types set on the input
and the output dont match
--*/
@@ -542,7 +607,11 @@ HRESULT COutPin::ChangeMediaTypeFromInpin(
SetState(DeviceStreamState_Disabled);
DMFTCHECKHR_GOTO(FlushQueues(),done);
DMFTCHECKNULL_GOTO(m_queue,done, E_UNEXPECTED); // The queue should alwaye be set
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ hr = m_queue->RecreateTeeByAllocatorMode(pInMediatype, pOutMediaType, m_spDxgiManager.Get(), m_allocatorUsage, m_spDefaultAllocator.get());
+#else
hr = m_queue->RecreateTee(pInMediatype, pOutMediaType, m_spDxgiManager.Get());
+#endif // ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
if ( SUCCEEDED( hr ) )
{
(VOID)setMediaType( pOutMediaType );
@@ -583,10 +652,10 @@ STDMETHODIMP COutPin::GetOutputStreamInfo(
/*++
COutPin::ProcessOutput
Description:
- called from the Device Transfrom when the transform manager demands output samples..
+ called from the Device Transform when the transform manager demands output samples..
If we have samples we forward it.
- If we are a photo pin then we forward only if trigger is sent. We ask the devicetransform if we have recieved the transform or not.
- If we have recieved the sample and we are passing out a sample we should reset the trigger set on the Device Transform
+ If we are a photo pin then we forward only if trigger is sent. We ask the devicetransform if we have received the transform or not.
+ If we have received the sample and we are passing out a sample we should reset the trigger set on the Device Transform
--*/
STDMETHODIMP COutPin::ProcessOutput(_In_ DWORD dwFlags,
@@ -663,18 +732,9 @@ STDMETHODIMP CAsyncInPin::SendSample(_In_ IMFSample *pSample)
{
HRESULT hr = S_OK;
CAutoLock Lock(lock());
- if (!m_bFlushing)
+ if (SUCCEEDED(Active()))
{
DMFTCHECKHR_GOTO(MFPutWorkItem(m_dwWorkQueueId, static_cast<IMFAsyncCallback*>(m_asyncCallback.Get()), pSample), done);
- if (1 == InterlockedIncrement(&m_dwSamplesInFlight))
- {
- ResetEvent(m_hHandle);
- }
- }
- else
- {
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! 0x%p Pin Flushing %d",this, streamId());
- // Let the sample fall through
}
done:
return hr;
@@ -682,18 +742,20 @@ done:
STDMETHODIMP CAsyncInPin::Init()
{
- m_asyncCallback = new (std::nothrow) CDMFTAsyncCallback<CAsyncInPin, &CAsyncInPin::Invoke>(this);
+ m_asyncCallback = new (std::nothrow) CDMFTAsyncCallback<CAsyncInPin, &CAsyncInPin::Invoke>(this, m_dwWorkQueueId);
if (!m_asyncCallback)
throw bad_alloc();
return S_OK;
}
+// Pass a secure frame buffer to our AVstream driver.
HRESULT CAsyncInPin::Invoke( _In_ IMFAsyncResult* pResult )
{
HRESULT hr = S_OK;
ComPtr<IUnknown> spUnknown;
ComPtr<IMFSample> spSample;
+ DMFTCHECKHR_GOTO(Active(), done);
DMFTCHECKNULL_GOTO(pResult, done, E_UNEXPECTED);
DMFTCHECKHR_GOTO(pResult->GetState(&spUnknown), done);
@@ -701,46 +763,26 @@ HRESULT CAsyncInPin::Invoke( _In_ IMFAsyncResult* pResult )
DMFTCHECKNULL_GOTO(spSample.Get(), done, E_INVALIDARG);
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ //
+ // Do secure buffer post-processing.
+ //
+ RETURN_IF_FAILED(ForwardSecureBuffer(spSample.Get()));
+#endif // ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
COutPin *poPin = static_cast<COutPin*>(m_outpin.Get());
DMFTCHECKHR_GOTO(poPin->AddSample(spSample.Get(), this), done);
-
- if (0 == InterlockedDecrement(&m_dwSamplesInFlight))
- {
- // No samples in flight.. Set the Event
- SetEvent(m_hHandle);
- }
-
done:
return hr;
}
-
-
-STDMETHODIMP CAsyncInPin::FlushQueues()
+STDMETHODIMP_(VOID) CAsyncInPin::ShutdownPin()
{
- HRESULT hr = S_OK;
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Entering ");
- // Flush in async mode else it is a NOOP
- {
- CAutoLock Lock(lock());
- if (m_bFlushing)
- {
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Pin %d Already Flushing ", streamId());
- goto done;
- }
- m_bFlushing = TRUE;
- }
- //
- // Wait for the IOs to drain
- //
- WaitForSingleObject(m_hHandle, INFINITE);
+ CAutoLock Lock(lock());
+ if (m_asyncCallback.Get())
{
- CAutoLock Lock(lock());
- m_bFlushing = FALSE;
+ (VOID)m_asyncCallback->Shutdown(); //Break reference with the parent
}
-done:
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr);
- return hr;
+ CInPin::ShutdownPin();
}
//
@@ -808,6 +850,7 @@ STDMETHODIMP CTranslateOutPin::AddMediaType(
done:
return hr;
}
+
STDMETHODIMP_(BOOL) CTranslateOutPin::IsMediaTypeSupported(
_In_ IMFMediaType *pMediaType,
_When_(ppIMFMediaTypeFull != nullptr, _Outptr_result_maybenull_)
@@ -824,9 +867,10 @@ STDMETHODIMP_(BOOL) CTranslateOutPin::IsMediaTypeSupported(
if (found != m_TranslatedMediaTypes.end())
{
+ ComPtr<IMFMediaType> spMediaType = (*found).second;
if (ppIMFMediaTypeFull)
{
- *ppIMFMediaTypeFull = (*found).second;
+ *ppIMFMediaTypeFull = spMediaType.Detach();
}
return true;
}
@@ -836,3 +880,24 @@ STDMETHODIMP_(BOOL) CTranslateOutPin::IsMediaTypeSupported(
return CBasePin::IsMediaTypeSupported(pMediaType,ppIMFMediaTypeFull);
}
}
+
+HRESULT CTranslateOutPin::ChangeMediaTypeFromInpin(
+ _In_ IMFMediaType *pInMediatype,
+ _In_ IMFMediaType* pOutMediaType,
+ _In_ DeviceStreamState state)
+{
+ CAutoLock Lock(lock());
+ //
+ // Set the state to disabled and while going out we will reset the state back to the requested state
+ // Flush so that we drop any samples we have in store!!
+ //
+ SetState(DeviceStreamState_Disabled);
+ RETURN_IF_FAILED(FlushQueues());
+ RETURN_HR_IF_NULL(E_UNEXPECTED, m_queue); // The queue should always be set
+ RETURN_IF_FAILED(m_queue->RecreateTee(pInMediatype, pOutMediaType, m_spDxgiManager.Get()));
+
+ (VOID)setMediaType(pOutMediaType);
+ (VOID)SetState(state);
+
+ return S_OK;
+}
diff --git a/avstream/sampledevicemft/basepin.h b/avstream/sampledevicemft/basepin.h
index faafd759..cce17d0b 100644
--- a/avstream/sampledevicemft/basepin.h
+++ b/avstream/sampledevicemft/basepin.h
@@ -369,7 +369,7 @@ public:
__requires_lock_held(m_lock)
__inline HRESULT Active()
{
- return (m_state == DeviceStreamState_Run)?S_OK:E_FAIL;
+ return (m_state == DeviceStreamState_Run)?S_OK:HRESULT_FROM_WIN32(ERROR_INVALID_STATE);
}
__inline DWORD streamId()
{
@@ -511,7 +511,7 @@ public:
return m_preferredStreamState;
}
- void ReleaseConnectedPins();
+ STDMETHOD_( VOID, ShutdownPin)();
protected:
ComPtr<IMFTransform> m_spSourceTransform; /*Source Transform i.e. DevProxy*/
@@ -520,15 +520,27 @@ protected:
DeviceStreamState m_preferredStreamState;
ComPtr<IMFMediaType> m_spPrefferedMediaType;
HANDLE m_waitInputMediaTypeWaiter; /*Set when the input media type is changed*/
+
+ // Helper functions
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ HRESULT ForwardSecureBuffer(
+ _In_ IMFSample *sample
+ );
+#endif
};
class COutPin: public CBasePin{
public:
- COutPin( _In_ ULONG id = 0,
+ COutPin(
+ _In_ ULONG id = 0,
_In_opt_ CMultipinMft *pparent = NULL,
- _In_ IKsControl* iksControl=NULL);
+ _In_ IKsControl* iksControl=NULL
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ , _In_ MFSampleAllocatorUsage allocatorUsage = MFSampleAllocatorUsage_DoesNotAllocate
+#endif
+ );
~COutPin();
STDMETHODIMP FlushQueues();
STDMETHODIMP AddPin(
@@ -541,7 +553,7 @@ public:
STDMETHODIMP GetOutputStreamInfo(
_Out_ MFT_OUTPUT_STREAM_INFO *pStreamInfo
);
- STDMETHODIMP ChangeMediaTypeFromInpin(
+ virtual STDMETHODIMP ChangeMediaTypeFromInpin(
_In_ IMFMediaType *pInMediatype,
_In_ IMFMediaType* pOutMediaType,
_In_ DeviceStreamState state );
@@ -560,6 +572,16 @@ public:
STDMETHODIMP_(VOID) SetFirstSample(
_In_ BOOL
);
+
+ STDMETHODIMP_(VOID) SetAllocator(
+ _In_ IMFVideoSampleAllocator* pAllocator
+ );
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ MFSampleAllocatorUsage GetSampleAllocatorUsage()
+ {
+ return m_allocatorUsage;
+ }
+#endif
UINT32 GetMediatypeCount()
{
return (UINT32)m_listOfMediaTypes.size();
@@ -568,13 +590,17 @@ public:
protected:
CPinQueue * m_queue; /* Queue where the sample will be stored*/
BOOL m_firstSample;
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ MFSampleAllocatorUsage m_allocatorUsage;
+#endif
+ wil::com_ptr_nothrow<IMFVideoSampleAllocator> m_spDefaultAllocator;
+
};
class CAsyncInPin: public CInPin {
public:
- STDMETHODIMP FlushQueues();
STDMETHODIMP SendSample(
_In_ IMFSample *
);
@@ -587,30 +613,19 @@ public:
_In_ ULONG ulPinId,
_In_ CMultipinMft *pParent) : CInPin(pAttributes,
ulPinId, pParent)
- , m_dwSamplesInFlight(0)
- , m_hHandle(INVALID_HANDLE_VALUE)
- , m_bFlushing(FALSE)
, m_asyncCallback(nullptr)
{
- m_hHandle = CreateEvent(NULL, TRUE, TRUE, L"Async_Pin Event");
- if (m_hHandle == nullptr)
- throw bad_alloc();
Init();
-
}
+ STDMETHOD_(VOID, ShutdownPin)();
~CAsyncInPin()
{
FlushQueues();
- CloseHandle(m_hHandle);
- m_hHandle = INVALID_HANDLE_VALUE;
}
ComPtr<CDMFTAsyncCallback<CAsyncInPin,&CAsyncInPin::Invoke> > m_asyncCallback; // Callback object
- HANDLE m_hHandle; // Handles to keep flush state
- DWORD m_dwSamplesInFlight; // Samples in flight i.e. waiting for the callback functions to be called
- BOOL m_bFlushing;
////////////////////////////////////////////////////////////////////////////////////////
// End of Asynchronous callback definitions
////////////////////////////////////////////////////////////////////////////////////////
@@ -628,7 +643,12 @@ class CTranslateOutPin : public COutPin {
public:
CTranslateOutPin(_In_ ULONG id = 0,
_In_opt_ CMultipinMft *pparent = NULL,
- _In_ IKsControl* iksControl = NULL) : COutPin(id, pparent, iksControl)
+ _In_ IKsControl* iksControl = NULL)
+ : COutPin(id, pparent, iksControl
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ , MFSampleAllocatorUsage_UsesCustomAllocator
+#endif
+ )
{
SetUINT32(MF_SD_VIDEO_SPHERICAL, TRUE);
}
@@ -639,8 +659,14 @@ public:
_In_ IMFMediaType *pMediaType,
_When_(ppIMFMediaTypeFull != nullptr, _Outptr_result_maybenull_)
IMFMediaType **ppIMFMediaTypeFull);
+ STDMETHOD(ChangeMediaTypeFromInpin)(
+ _In_ IMFMediaType *pInMediatype,
+ _In_ IMFMediaType* pOutMediaType,
+ _In_ DeviceStreamState state);
+
protected:
map<IMFMediaType*, IMFMediaType*> m_TranslatedMediaTypes;
};
+
diff --git a/avstream/sampledevicemft/common.h b/avstream/sampledevicemft/common.h
index 72242fa3..bc6bbf28 100644
--- a/avstream/sampledevicemft/common.h
+++ b/avstream/sampledevicemft/common.h
@@ -291,7 +291,7 @@ HRESULT ExceptionBoundary(Lambda&& lambda)
}
catch (...)
{
- return E_FAIL;
+ return E_UNEXPECTED;
}
}
@@ -581,7 +581,7 @@ public:
pcbBuffer);
if (dwHeightInPixels* abs(*plStride) > *pcbBuffer)
{
- hr = E_FAIL;
+ hr = E_UNEXPECTED;
}
} else if (m_sp2DBuffer)
{
@@ -652,6 +652,13 @@ HRESULT IsDXFormatSupported(
_Outptr_opt_ ID3D11Device** ppDevice,
_In_opt_ PUINT32 pSupportedFormat);
+HRESULT ConfigureAllocator(
+ _In_ IMFMediaType* pOutputMediaType,
+ _In_ GUID streamCategory,
+ _In_ IUnknown* pDeviceManagerUnk,
+ _In_ BOOL &isDxAllocator,
+ _In_ IMFVideoSampleAllocator* pAllocator);
+
HRESULT CreateAllocator( _In_ IMFMediaType* pOutputMediaType,
_In_ GUID streamCategory,
_In_ IUnknown* pDeviceManagerUnk,
diff --git a/avstream/sampledevicemft/contosodevice.h b/avstream/sampledevicemft/contosodevice.h
new file mode 100644
index 00000000..66759f69
--- /dev/null
+++ b/avstream/sampledevicemft/contosodevice.h
@@ -0,0 +1,28 @@
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+// PARTICULAR PURPOSE.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// The Contoso device comes with an SDK
+// that defines various Contoso-specific types,
+// all of which have CONTOSO in their names.
+
+#pragma once
+
+// This payload is used when sending a KSPROPERTY_CONTOSODEVICE_PROCESSBUFFER.
+struct CONTOSODEVICE_PROCESSBUFFER_PAYLOAD
+{
+ GUID identifier;
+ DWORD size;
+};
+
+// Define a custom property set for driver communications.
+// {C5175EE2-583E-43A2-8C26-765287BCEB9D}
+#define STATIC_PROPSETID_CONTOSODEVICE\
+ 0xc5175ee2, 0x583e, 0x43a2, 0x8c, 0x26, 0x76, 0x52, 0x87, 0xbc, 0xeb, 0x9d
+DEFINE_GUIDSTRUCT("C5175EE2-583E-43A2-8C26-765287BCEB9D", PROPSETID_CONTOSODEVICE);
+#define PROPSETID_CONTOSODEVICE DEFINE_GUIDNAMED(PROPSETID_CONTOSODEVICE)
+#define KSPROPERTY_CONTOSODEVICE_PROCESSBUFFER 0 // Send a frame buffer ID to the driver.
+
diff --git a/avstream/sampledevicemft/custompin.cpp b/avstream/sampledevicemft/custompin.cpp
index 00edb329..edb5fadb 100644
--- a/avstream/sampledevicemft/custompin.cpp
+++ b/avstream/sampledevicemft/custompin.cpp
@@ -35,7 +35,7 @@ STDMETHODIMP CCustomPin::SendSample(
// Log sample and exit.. The pipeline will just keep on churning more samples till
// We go into the stop state
//
- DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Custom Pin %d recieved Sample %p", streamId(), pSample);
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Custom Pin %d received Sample %p", streamId(), pSample);
return S_OK;
}
diff --git a/avstream/sampledevicemft/dllmain.cpp b/avstream/sampledevicemft/dllmain.cpp
index 6978a9d5..88bfe6ab 100644
--- a/avstream/sampledevicemft/dllmain.cpp
+++ b/avstream/sampledevicemft/dllmain.cpp
@@ -196,13 +196,35 @@ STDMETHODIMP_(BOOL) WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, void *)
DisableThreadLibraryCalls(hInstance);
#ifdef MF_WPP
WPP_INIT_TRACING(L"MultiPinMft");
+
+ // Hook up WIL tracing to our trace provider.
+ wil::SetResultLoggingCallback(
+ [](const wil::FailureInfo &failure)
+ {
+ wchar_t debugString[2048];
+ if (SUCCEEDED(wil::GetFailureLogString(debugString, ARRAYSIZE(debugString), failure)))
+ {
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_ERROR, L"%S", debugString);
+ }
+ else
+ {
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_ERROR,
+ L"File: %s, Line: %u, Error: 0x%08X - %S\n",
+ failure.pszFile,
+ failure.uLineNumber,
+ failure.hr,
+ failure.pszMessage);
+ }
+ }
+ );
#endif
}
else
if (dwReason == DLL_PROCESS_DETACH)
{
#ifdef MF_WPP
- WPP_CLEANUP();
+ wil::SetResultLoggingCallback(nullptr);
+ WPP_CLEANUP();
#endif
}
return TRUE;
diff --git a/avstream/sampledevicemft/multipinmft.cpp b/avstream/sampledevicemft/multipinmft.cpp
index 3467870b..f4fe3d27 100644
--- a/avstream/sampledevicemft/multipinmft.cpp
+++ b/avstream/sampledevicemft/multipinmft.cpp
@@ -1322,6 +1322,54 @@ done:
}
#endif
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+//
+// IMFSampleAllocatorControl Inferface function declarations
+//
+
+STDMETHODIMP CMultipinMft::SetDefaultAllocator(
+ _In_ DWORD dwOutputStreamID,
+ _In_ IUnknown *pAllocator
+)
+{
+ CAutoLock Lock(m_critSec);
+
+ // SetAllocator will be called on the streamId that returns MFSampleAllocatorMode_Default
+ wil::com_ptr_nothrow<COutPin> outPin = GetOutPin(dwOutputStreamID);
+ RETURN_HR_IF_NULL(E_INVALIDARG, outPin);
+ RETURN_HR_IF_NULL(E_INVALIDARG, pAllocator);
+
+ wil::com_ptr_nothrow<IMFVideoSampleAllocator> defaultAllocator;
+ RETURN_IF_FAILED(pAllocator->QueryInterface(&defaultAllocator));
+ outPin->SetAllocator(defaultAllocator.get());
+
+ return S_OK;
+}
+
+STDMETHODIMP CMultipinMft::GetAllocatorUsage(
+ _In_ DWORD dwOutputStreamID,
+ _Out_ DWORD* pdwInputStreamID,
+ _Out_ MFSampleAllocatorUsage* peUsage
+)
+{
+ CAutoLock Lock(m_critSec);
+
+ RETURN_HR_IF_NULL(E_INVALIDARG, peUsage);
+
+ wil::com_ptr_nothrow<COutPin> outPin = GetOutPin(dwOutputStreamID);
+ RETURN_HR_IF_NULL(MF_E_INVALIDSTREAMNUMBER, outPin);
+ *peUsage = outPin->GetSampleAllocatorUsage();
+
+ if (*peUsage == MFSampleAllocatorUsage_DoesNotAllocate)
+ {
+ RETURN_HR_IF_NULL(E_INVALIDARG, pdwInputStreamID);
+ RETURN_IF_FAILED(GetConnectedInpin((ULONG)dwOutputStreamID, *(ULONG*)pdwInputStreamID));
+ }
+
+ return S_OK;
+}
+#endif // ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+
//
// HELPER FUNCTIONS
//
@@ -1513,7 +1561,7 @@ HRESULT CMultipinMft::BridgeInputPinOutputPin(
HRESULT hr = S_OK;
ULONG ulIndex = 0;
ULONG ulAddedMediaTypeCount = 0;
- ComPtr<IMFMediaType> pMediaType = nullptr;
+ ComPtr<IMFMediaType> spMediaType;
DMFTCHECKNULL_GOTO( piPin, done, E_INVALIDARG );
DMFTCHECKNULL_GOTO( poPin, done, E_INVALIDARG );
@@ -1523,19 +1571,17 @@ HRESULT CMultipinMft::BridgeInputPinOutputPin(
// sure any pin advertised supports at least one media type. The pipeline doesn't
// like pins with no media types
//
- while ( SUCCEEDED( hr = piPin->GetMediaTypeAt( ulIndex++, &pMediaType )))
+ while ( SUCCEEDED( hr = piPin->GetMediaTypeAt( ulIndex++, spMediaType.ReleaseAndGetAddressOf() )))
{
GUID subType = GUID_NULL;
- DMFTCHECKHR_GOTO( pMediaType->GetGUID(MF_MT_SUBTYPE,&subType), done );
+ DMFTCHECKHR_GOTO( spMediaType->GetGUID(MF_MT_SUBTYPE,&subType), done );
{
- DMFTCHECKHR_GOTO(hr = poPin->AddMediaType(NULL, pMediaType.Get() ), done );
+ DMFTCHECKHR_GOTO(hr = poPin->AddMediaType(NULL, spMediaType.Get() ), done );
if (hr == S_OK)
{
ulAddedMediaTypeCount++;
}
}
-
- pMediaType = nullptr;
}
if (ulAddedMediaTypeCount == 0)
{
@@ -1679,7 +1725,7 @@ STDMETHODIMP CMultipinMft::Shutdown(
CInPin *pInPin = static_cast<CInPin *>(m_InPins[ulIndex]);
// Deref on the connected outpins to break reference loop
- pInPin->ReleaseConnectedPins();
+ (VOID)pInPin->ShutdownPin();
}
#if defined (MF_DEVICEMFT_ALLOW_MFT0_LOAD) && defined (MFT_UNIQUE_METHOD_NAMES)
for (ULONG ulIndex = 0, ulSize = (ULONG)m_OutPins.size(); ulIndex < ulSize; ulIndex++)
diff --git a/avstream/sampledevicemft/multipinmft.h b/avstream/sampledevicemft/multipinmft.h
index 080f4a7a..70367f1d 100644
--- a/avstream/sampledevicemft/multipinmft.h
+++ b/avstream/sampledevicemft/multipinmft.h
@@ -48,6 +48,9 @@ class CMultipinMft :
, public IMFGetService
#endif
, public CDMFTModuleLifeTimeManager
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ , public IMFSampleAllocatorControl
+#endif
{
friend class CPinCreationFactory;
public:
@@ -275,7 +278,22 @@ public:
}
#endif
-
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ //
+ // IMFSampleAllocatorControl Inferface function declarations
+ //
+
+ STDMETHOD(SetDefaultAllocator)(
+ _In_ DWORD dwOutputStreamID,
+ _In_ IUnknown *pAllocator
+ );
+
+ STDMETHOD(GetAllocatorUsage)(
+ _In_ DWORD dwOutputStreamID,
+ _Out_ DWORD* pdwInputStreamID,
+ _Out_ MFSampleAllocatorUsage* peUsage
+ );
+#endif
static STDMETHODIMP CreateInstance(
REFIID iid, void **ppMFT);
diff --git a/avstream/sampledevicemft/multipinmft.vcxproj b/avstream/sampledevicemft/multipinmft.vcxproj
index 0f560e2c..1a0716bb 100644
--- a/avstream/sampledevicemft/multipinmft.vcxproj
+++ b/avstream/sampledevicemft/multipinmft.vcxproj
@@ -262,9 +262,17 @@
<None Exclude="@(None)" Include="*.txt;*.htm;*.html" />
<None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" />
<None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" />
+ <None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <Import Project="packages\Microsoft.Windows.ImplementationLibrary.1.0.190716.2\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('packages\Microsoft.Windows.ImplementationLibrary.1.0.190716.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('packages\Microsoft.Windows.ImplementationLibrary.1.0.190716.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.Windows.ImplementationLibrary.1.0.190716.2\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
+ </Target>
</Project> \ No newline at end of file
diff --git a/avstream/sampledevicemft/multipinmft.vcxproj.Filters b/avstream/sampledevicemft/multipinmft.vcxproj.Filters
index e06f675d..36af8e37 100644
--- a/avstream/sampledevicemft/multipinmft.vcxproj.Filters
+++ b/avstream/sampledevicemft/multipinmft.vcxproj.Filters
@@ -42,5 +42,6 @@
<None Include="Source.def">
<Filter>Source Files</Filter>
</None>
+ <None Include="packages.config" />
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/avstream/sampledevicemft/multipinmfthelpers.cpp b/avstream/sampledevicemft/multipinmfthelpers.cpp
index 904625ad..34cebe8b 100644
--- a/avstream/sampledevicemft/multipinmfthelpers.cpp
+++ b/avstream/sampledevicemft/multipinmfthelpers.cpp
@@ -16,8 +16,7 @@ class CMediaTypePrinter;
//
CPinQueue::CPinQueue( _In_ DWORD dwPinId ,
_In_ IMFDeviceTransform* pParent)
-: m_teer(0),
- m_dwInPinId(dwPinId),
+ :m_dwInPinId(dwPinId),
m_pTransform(pParent),
m_cRef(1)
@@ -30,6 +29,7 @@ CPinQueue::CPinQueue( _In_ DWORD dwPinId ,
}
CPinQueue::~CPinQueue( )
{
+ Ctee::ReleaseTee(m_spTeer);
}
/*++
@@ -59,10 +59,10 @@ STDMETHODIMP_(VOID) CPinQueue::InsertInternal( _In_ IMFSample *pSample )
STDMETHODIMP CPinQueue::Insert( _In_ IMFSample *pSample )
//
-//m_teer is the wraptee.. this could be a null tee which is a passthrough, an xvp tee which inserts an xvp into the queue etc
+//m_spTeer is the wraptee.. this could be a null tee which is a passthrough, an xvp tee which inserts an xvp into the queue etc
//
{
- return m_teer->PassThrough( pSample );
+ return m_spTeer->PassThrough( pSample );
}
/*++
@@ -97,9 +97,9 @@ VOID CPinQueue::Clear( )
// Stop the tees
// Execute Flush
//
- if (m_teer)
+ if (m_spTeer)
{
- m_teer->Stop();
+ m_spTeer->Stop();
}
while ( !Empty() )
@@ -114,62 +114,99 @@ Description:
RecreateTee creates the underlying Tees in the queue. It accepts the input media type
which is the media type set on the input pin and the output mediatype, which (duh) is the
media type on the output pin
- It also takes an IUnknown which is the D3D Manager. if it is valid we might use it if we
+ It also takes an IUnknown which is the D3D Manager. if it is valid we might use it if we
have an xvp in the path i.e. inputMediatype =! outputMediatype
--*/
-STDMETHODIMP CPinQueue::RecreateTee( _In_ IMFMediaType *inMediatype,
+STDMETHODIMP CPinQueue::RecreateTee(_In_ IMFMediaType *inMediatype,
_In_ IMFMediaType *outMediatype,
- _In_opt_ IUnknown* punkManager )
+ _In_opt_ IUnknown* punkManager)
{
HRESULT hr = S_OK;
DMFT_conversion_type operation = DeviceMftTransformTypeIllegal;
-
- SAFE_DELETE(m_teer); // Should release the reference
- CNullTee *nulltee = new (std::nothrow) CNullTee(this);
- DMFTCHECKNULL_GOTO( nulltee, done, E_OUTOFMEMORY);
+ Ctee::ReleaseTee(m_spTeer);
+
+ ComPtr<CNullTee> spNulltee = new (std::nothrow) CNullTee(this);
+ DMFTCHECKNULL_GOTO(spNulltee.Get(), done, E_OUTOFMEMORY);
DMFTCHECKHR_GOTO(CompareMediaTypesForConverter(inMediatype, outMediatype, &operation), done);
if (operation == DeviceMftTransformTypeDecoder)
{
// Decoder needed
- CDecoderTee* pDecTee = new (std::nothrow) CDecoderTee(nulltee,
+ CDecoderTee* pDecTee = new (std::nothrow) CDecoderTee(spNulltee.Get(),
static_cast<CMultipinMft*>(m_pTransform)->GetQueueId(),
pinCategory());
DMFTCHECKNULL_GOTO(pDecTee, done, E_OUTOFMEMORY);
(void)pDecTee->SetD3DManager(punkManager);
- DMFTCHECKHR_GOTO(pDecTee->SetMediaTypes(inMediatype, outMediatype),done);
- m_teer = dynamic_cast<Ctee*>(pDecTee);
+ DMFTCHECKHR_GOTO(pDecTee->SetMediaTypes(inMediatype, outMediatype), done);
+ m_spTeer = pDecTee;
}
- else if (operation == DeviceMftTransformTypeXVP)
+ else if (operation == DeviceMftTransformTypeXVP)
{
- CXvptee* pXvptee = new (std::nothrow) CXvptee(nulltee, pinCategory());
+ CXvptee* pXvptee = new (std::nothrow) CXvptee(spNulltee.Get(), pinCategory());
DMFTCHECKNULL_GOTO(pXvptee, done, E_OUTOFMEMORY);
- (void)pXvptee->SetD3DManager( punkManager );
- DMFTCHECKHR_GOTO(pXvptee->SetMediaTypes( inMediatype, outMediatype ),done);
- m_teer = dynamic_cast< Ctee* >( pXvptee );
+ (void)pXvptee->SetD3DManager(punkManager);
+ DMFTCHECKHR_GOTO(pXvptee->SetMediaTypes(inMediatype, outMediatype), done);
+ m_spTeer = pXvptee;
}
else
{
- m_teer = nulltee; /*A simple passthrough*/
+ m_spTeer = spNulltee.Get(); /*A simple passthrough*/
}
done:
- DMFTRACE( DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr );
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! exiting %x = %!HRESULT!", hr, hr);
if (FAILED(hr))
{
- if (m_teer){
- delete(m_teer);
- m_teer = NULL;
+ Ctee::ReleaseTee(m_spTeer);
+ }
+ return hr;
+}
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+STDMETHODIMP CPinQueue::RecreateTeeByAllocatorMode(
+ _In_ IMFMediaType* inMediatype,
+ _In_ IMFMediaType* outMediatype,
+ _In_opt_ IUnknown* punkManager,
+ _In_ MFSampleAllocatorUsage allocatorUsage,
+ _In_opt_ IMFVideoSampleAllocator* pAllocator)
+{
+ HRESULT hr = S_OK;
+
+ Ctee::ReleaseTee(m_spTeer);// Should release the reference
+
+ wistd::unique_ptr<CNullTee> nulltee = wil::make_unique_nothrow<CNullTee>(this);
+ RETURN_IF_NULL_ALLOC(nulltee);
+
+ if (allocatorUsage == MFSampleAllocatorUsage_DoesNotAllocate)
+ {
+ m_spTeer.Attach(nulltee.release()); /*A simple passthrough*/
+ }
+ else
+ {
+ wistd::unique_ptr<CSampleCopytee> sampleCopytee;
+ RETURN_IF_NULL_ALLOC(sampleCopytee);
+ (void)sampleCopytee->SetD3DManager(punkManager);
+
+ if (allocatorUsage == MFSampleAllocatorUsage_UsesProvidedAllocator)
+ {
+ RETURN_HR_IF_NULL(E_INVALIDARG, pAllocator);
+ sampleCopytee = wil::make_unique_nothrow<CSampleCopytee>(nulltee.release(), pinCategory(), pAllocator);
+ }
+ else
+ {
+ sampleCopytee = wil::make_unique_nothrow<CSampleCopytee>(nulltee.release(), pinCategory(), nullptr);
}
+ RETURN_IF_FAILED(sampleCopytee->SetMediaTypes(inMediatype, outMediatype));
+ m_spTeer.Attach(sampleCopytee.release());
}
+
return hr;
}
-
+#endif // ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
#ifdef MF_DEVICEMFT_ADD_GRAYSCALER_
STDMETHODIMP CPinQueueWithGrayScale::RecreateTee( _In_ IMFMediaType *inMediatype,
_In_ IMFMediaType *outMediatype,
@@ -183,7 +220,7 @@ STDMETHODIMP CPinQueueWithGrayScale::RecreateTee( _In_ IMFMediaType *inMediatyp
DMFTCHECKHR_GOTO(CPinQueue::RecreateTee(inMediatype,
outMediatype,
punkManager),done);
- DMFTCHECKNULL_GOTO(m_teer, done, E_UNEXPECTED);
+ DMFTCHECKNULL_GOTO(m_spTeer, done, E_UNEXPECTED);
// Wrap the media type with Gray scale tee only if the input media type is a YUY2, UYVY, NV12 or RGB32
DMFTCHECKHR_GOTO(inMediatype->GetGUID(MF_MT_SUBTYPE, &gInputSubType), done);
if (IsEqualCLSID(gInputSubType, MFVideoFormat_NV12)
@@ -192,9 +229,9 @@ STDMETHODIMP CPinQueueWithGrayScale::RecreateTee( _In_ IMFMediaType *inMediatyp
||IsEqualCLSID(gInputSubType, MFVideoFormat_RGB32))
{
CGrayTee *pTee = NULL;
- pTee = new (std::nothrow) CGrayTee(m_teer);
+ pTee = new (std::nothrow) CGrayTee(m_spTeer);
DMFTCHECKHR_GOTO(pTee->SetMediaTypes(inMediatype, outMediatype), done);
- m_teer = dynamic_cast< Ctee* >(pTee);
+ m_spTeer = dynamic_cast< Ctee* >(pTee);
}
else
{
@@ -251,9 +288,9 @@ STDMETHODIMP CWrapTee::PassThrough( _In_ IMFSample* pInSample )
DMFTCHECKNULL_GOTO(pInSample, done, S_OK); // pass through for no sample
DMFTCHECKHR_GOTO(Do(pInSample, &pOutSample,newSample),done);
- if (m_objectWrapped)
+ if (m_spObjectWrapped)
{
- if (SUCCEEDED(hr = m_objectWrapped->PassThrough( pOutSample )))
+ if (SUCCEEDED(hr = m_spObjectWrapped->PassThrough( pOutSample )))
{
//@@@@README There is a very bad bug in the pipeline that the device transform manager
// is not releasing the reference on the sample when it is passed to the device MFT so any
@@ -289,7 +326,7 @@ HRESULT CVideoProcTee::SetMediaTypes(_In_ IMFMediaType* pInMediaType, _In_ IMFMe
ComPtr<IMFTransform> spTransform;
DMFTCHECKHR_GOTO(CWrapTee::SetMediaTypes(pInMediaType, pOutMediaType),done);
DMFTCHECKHR_GOTO(Configure(pInMediaType, pOutMediaType, spTransform.GetAddressOf()), done);
- m_videoProcessor = spTransform.Detach();
+ m_spVideoProcessor = spTransform.Detach();
//
// Start streaming
//
@@ -298,6 +335,8 @@ done:
return hr;
}
+
+
HRESULT CVideoProcTee::CreateAllocator()
{
HRESULT hr = S_OK;
@@ -307,18 +346,37 @@ HRESULT CVideoProcTee::CreateAllocator()
return S_OK;
}
- if (m_spAllocator.Get())
+ if (m_spPrivateAllocator)
{
// Release what we have currently
- DMFTCHECKHR_GOTO(m_spAllocator->UninitializeSampleAllocator(), done);
- m_spAllocator = nullptr;
+ RETURN_IF_FAILED(m_spPrivateAllocator->UninitializeSampleAllocator());
+ m_spPrivateAllocator = nullptr;
+ }
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ if (m_spDefaultAllocator)
+ {
+ // Configure default allocator
+ m_spDefaultAllocator->UninitializeSampleAllocator();
+ RETURN_IF_FAILED(::ConfigureAllocator(
+ m_pOutputMediaType.Get(),
+ m_streamCategory,
+ m_spDeviceManagerUnk.Get(),
+ m_fSetD3DManager,
+ m_spDefaultAllocator.Get()));
+ }
+ else
+#endif // ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ {
+ // Create and configure private allocator
+ RETURN_IF_FAILED(MFCreateVideoSampleAllocatorEx(IID_PPV_ARGS(m_spPrivateAllocator.ReleaseAndGetAddressOf())));
+ RETURN_IF_FAILED(::ConfigureAllocator(
+ m_pOutputMediaType.Get(),
+ m_streamCategory,
+ m_spDeviceManagerUnk.Get(),
+ m_fSetD3DManager,
+ m_spPrivateAllocator.Get()));
}
- DMFTCHECKHR_GOTO(::CreateAllocator(m_pOutputMediaType.Get(),
- m_streamCategory, m_spDeviceManagerUnk.Get(),
- m_fSetD3DManager,
- m_spAllocator.GetAddressOf()), done);
-done:
return hr;
}
@@ -342,6 +400,7 @@ CXvptee::~CXvptee()
HRESULT CXvptee::StartStreaming()
{
HRESULT hr = S_OK;
+ CAutoLock Lock(m_Lock);
DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0), done); // ulParam set to zero
DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0), done); // ulParam set to zero
done:
@@ -351,6 +410,8 @@ done:
HRESULT CXvptee::StopStreaming()
{
HRESULT hr = S_OK;
+ CAutoLock Lock(m_Lock);
+ SetAsyncStatus(MF_E_SHUTDOWN);
DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, 0), done); // Flush the stream
DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_END_OF_STREAM, 0), done); // Notify end of stream
DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_END_STREAMING, 0), done); // Notify end of streaming
@@ -374,17 +435,17 @@ STDMETHODIMP CXvptee::Do(_In_ IMFSample *pSample, _Outptr_ IMFSample** ppOutSamp
MFT_OUTPUT_DATA_BUFFER outputSample;
ComPtr <IMFSample> spXVPOutputSample;
DWORD dwStatus = 0;
+ CAutoLock Lock(m_Lock);
DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! XVP ProcessOutput Processing Sample =%p", pSample);
DMFTCHECKNULL_GOTO(ppOutSample, done, E_INVALIDARG);
-
*ppOutSample = nullptr;
-
+ DMFTCHECKHR_GOTO(GetAsyncStatus(), done);
DMFTCHECKHR_GOTO(Transform()->MFTProcessInput(0, pSample, 0),done);
outputSample.dwStreamID = 0;
outputSample.pSample = NULL;
- DMFTCHECKHR_GOTO(m_spAllocator->AllocateSample(&outputSample.pSample), done);
+ DMFTCHECKHR_GOTO(m_spPrivateAllocator->AllocateSample(&outputSample.pSample), done);
hr = Transform()->MFTProcessOutput(0, 1, &outputSample, &dwStatus);
@@ -492,16 +553,18 @@ done:
CDecoderTee::~CDecoderTee()
{
(VOID)StopStreaming();
- if (m_spAllocator)
+ MFUnlockWorkQueue(m_dwCameraStreamWorkQueueId);
+ if (m_spPrivateAllocator)
{
- m_spAllocator->UninitializeSampleAllocator();
- m_spAllocator = nullptr;
+ m_spPrivateAllocator->UninitializeSampleAllocator();
+ m_spPrivateAllocator = nullptr;
}
}
HRESULT CDecoderTee::StartStreaming()
{
HRESULT hr = S_OK;
+ CAutoLock Lock(&m_Lock);
DMFTCHECKNULL_GOTO(Transform(), done, MF_E_UNEXPECTED);
DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0), done);
DMFTCHECKHR_GOTO(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0), done);
@@ -512,13 +575,11 @@ HRESULT CDecoderTee::StartStreaming()
HRESULT CDecoderTee::StopStreaming()
{
HRESULT hr = S_OK;
- ComPtr<IMFTransform> spTransform = Transform();
+ ComPtr<IMFTransform> spTransform;
{
- CAutoLock Lock(&m_critSec);
- if (m_hSyncHandle)
- {
- ResetEvent(m_hSyncHandle);
- }
+ CAutoLock Lock(&m_Lock);
+ spTransform = Transform();
+ SetAsyncStatus(MF_E_SHUTDOWN);
}
if (spTransform.Get())
{
@@ -531,15 +592,7 @@ HRESULT CDecoderTee::StopStreaming()
{
(void)spShutdown->Shutdown();
}
- m_critSec.Lock();
- SetAsyncStatus(MF_E_SHUTDOWN);
- MFUnlockWorkQueue(m_dwCameraStreamWorkQueueId);
- if (m_ulProcessOutputsInFlight > 0)
- {
- m_critSec.Unlock();
- WaitForSingleObject(m_hSyncHandle, INFINITE);
-
- }
+
spTransform = nullptr;
}
done:
@@ -553,17 +606,12 @@ STDMETHODIMP CDecoderTee::Configure(_In_opt_ IMFMediaType *inType,
HRESULT hr = S_OK;
ComPtr<IMFTransform> spTransform;
GUID gInSubType = GUID_NULL, gOutSubType = GUID_NULL;
+
DMFTCHECKNULL_GOTO(ppTransform, done, E_INVALIDARG);
DMFTCHECKNULL_GOTO(inType, done, E_INVALIDARG);
DMFTCHECKNULL_GOTO(outType, done, E_INVALIDARG);
*ppTransform = nullptr;
- SAFE_CLOSEHANDLE(m_hSyncHandle);
- m_hSyncHandle = CreateEvent(NULL,
- FALSE,
- TRUE,
- TEXT("SyncDecoderWaiter")
- );
if (!(SUCCEEDED(inType->GetGUID(MF_MT_SUBTYPE, &gInSubType))
&& SUCCEEDED(outType->GetGUID(MF_MT_SUBTYPE, &gOutSubType))))
{
@@ -592,11 +640,6 @@ STDMETHODIMP CDecoderTee::Configure(_In_opt_ IMFMediaType *inType,
}
DMFTCHECKNULL_GOTO(spTransform.Get(), done, E_UNEXPECTED);
- if (m_D3daware && SUCCEEDED(IsDXFormatSupported(reinterpret_cast<IMFDXGIDeviceManager*>(m_spDeviceManagerUnk.Get()), gOutSubType, nullptr, nullptr)))
- {
- DMFTCHECKHR_GOTO(spTransform->MFTProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, (ULONG_PTR)m_spDeviceManagerUnk.Get()), done);
- }
-
DMFTCHECKHR_GOTO(spTransform->MFTGetOutputStreamInfo(m_dwMFTOutputId, &outputStreamInfo), done);
m_bProducesSamples = (outputStreamInfo.dwFlags & (MFT_OUTPUT_STREAM_PROVIDES_SAMPLES | MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES));
@@ -608,7 +651,7 @@ STDMETHODIMP CDecoderTee::Configure(_In_opt_ IMFMediaType *inType,
}
// Create a callback for processoutputs to be called on
- m_asyncCallback = new (std::nothrow) CDMFTAsyncCallback<CDecoderTee, &CDecoderTee::Invoke>(this);
+ m_asyncCallback = new (std::nothrow) CDMFTAsyncCallback<CDecoderTee, &CDecoderTee::Invoke>(this, m_dwQueueId);
DMFTCHECKNULL_GOTO(m_asyncCallback.Get(), done, E_OUTOFMEMORY);
if (m_fAsyncMFT)
@@ -636,9 +679,10 @@ STDMETHODIMP CDecoderTee::Do(_In_ IMFSample* pSample, _Outptr_ IMFSample **ppout
{
HRESULT hr = S_OK;
ComPtr<IMFSample> spOutputSample;
+ CAutoLock lock(m_Lock);
ComPtr<IMFTransform> spTransform = Transform();
+
newSample = false;
- CAutoLock lock(m_critSec);
DMFTCHECKNULL_GOTO(ppoutSample, done, E_INVALIDARG);
*ppoutSample = nullptr;
DMFTCHECKHR_GOTO(GetAsyncStatus(), done);
@@ -663,7 +707,6 @@ STDMETHODIMP CDecoderTee::Do(_In_ IMFSample* pSample, _Outptr_ IMFSample **ppout
spInputSample.Detach();
hr = S_OK;
// Queue a work item for process output
- m_ulProcessOutputsInFlight++;
DMFTCHECKHR_GOTO(MFPutWorkItem(m_dwCameraStreamWorkQueueId, m_asyncCallback.Get(), nullptr), done);
break;
}
@@ -720,7 +763,7 @@ HRESULT CDecoderTee::Invoke(_In_ IMFAsyncResult* pResult)
ComPtr<IMFTransform> spDecoderTemp;
ComPtr<IMFSample> spOutputSample;
BOOL bSendSample = FALSE;
- CAutoLock lock(m_critSec);
+ CAutoLock lock(m_Lock);
spDecoderTemp = Transform();
@@ -748,12 +791,12 @@ HRESULT CDecoderTee::Invoke(_In_ IMFAsyncResult* pResult)
case METransformHaveOutput:
{
ComPtr<IMFSample> spDecodedSample;
- m_critSec.Unlock();
+ m_Lock.Unlock();
//
// The processoutput call blocks for H264 sometimes. This call back is serialized
//
hr = ProcessOutputSync(spDecodedSample.GetAddressOf());
- m_critSec.Lock();
+ m_Lock.Lock();
// Did we error out when we released the lock?
DMFTCHECKHR_GOTO(GetAsyncStatus(), done);
if (SUCCEEDED(hr))
@@ -780,13 +823,12 @@ HRESULT CDecoderTee::Invoke(_In_ IMFAsyncResult* pResult)
{
// Synchronous mode. We only need it for processoutputs
ComPtr<IMFSample> spDecodedSample;
- m_ulProcessOutputsInFlight--;
DMFTCHECKHR_GOTO(GetAsyncStatus(), done);
DMFTCHECKNULL_GOTO(pResult, done, E_UNEXPECTED);
DMFTCHECKHR_GOTO(pResult->GetStatus(), done);
- m_critSec.Unlock();
+ m_Lock.Unlock();
hr = ProcessOutputSync(spDecodedSample.GetAddressOf());
- m_critSec.Lock();
+ m_Lock.Lock();
if (SUCCEEDED(hr))
{
// send the sample on its way
@@ -805,9 +847,9 @@ done:
if (bSendSample && spOutputSample.Get())
{
- if (m_objectWrapped)
+ if (m_spObjectWrapped)
{
- hr = m_objectWrapped->PassThrough(spOutputSample.Get());
+ hr = m_spObjectWrapped->PassThrough(spOutputSample.Get());
spOutputSample = nullptr;
}
}
@@ -823,11 +865,6 @@ done:
{
SetAsyncStatus(hr);
}
- if (m_StoppedAndWaiting)
- {
- // Stop is waiting on the threads to run
- SetEvent(m_hSyncHandle);
- }
return hr;
}
@@ -836,11 +873,11 @@ done:
// is holding on to the buffers, could be the xvp then this function will error
// out the pipeline. you should see the ALLOCATOR_E_EMPTY error pop up
//
-_Ret_maybenull_ HRESULT CDecoderTee::GetSample( IMFSample** ppSample )
+HRESULT CDecoderTee::GetSample( IMFSample** ppSample )
{
- if (!m_bProducesSamples && m_spAllocator.Get())
+ if (!m_bProducesSamples && m_spPrivateAllocator.Get())
{
- return m_spAllocator->AllocateSample(ppSample);
+ return m_spPrivateAllocator->AllocateSample(ppSample);
}
return S_OK;
}
@@ -890,7 +927,7 @@ HRESULT CDecoderTee::ProcessFormatChange()
// Also note, The platform doesn't support dynamic media type changes from the stream coming from the
// source.
//
- ComPtr<IMFTransform> spXvp;
+ ComPtr<CXvptee> spXvpTee;
DMFTCHECKHR_GOTO(m_pOutputMediaType->GetGUID(MF_MT_SUBTYPE, &guidPreviousSubType), done);
for (DWORD i = 0; ; i++)
@@ -918,11 +955,11 @@ HRESULT CDecoderTee::ProcessFormatChange()
//
// Create the XVP and insert it into the chain manually. set the output to the mediatype requested by the platform
//
- CXvptee* pXvpTee = new (std::nothrow) CXvptee(m_objectWrapped ,m_streamCategory);
- DMFTCHECKNULL_GOTO(pXvpTee, done, E_OUTOFMEMORY);
- (VOID)pXvpTee->SetD3DManager(m_spDeviceManagerUnk.Get());
- DMFTCHECKHR_GOTO(pXvpTee->SetMediaTypes(spDecoderOutputMediaType.Get(), m_pOutputMediaType.Get()), done);
- m_objectWrapped = pXvpTee;
+ spXvpTee = new (std::nothrow) CXvptee(m_spObjectWrapped.Get() ,m_streamCategory);
+ DMFTCHECKNULL_GOTO(spXvpTee.Get(), done, E_OUTOFMEMORY);
+ (VOID)spXvpTee->SetD3DManager(m_spDeviceManagerUnk.Get());
+ DMFTCHECKHR_GOTO(spXvpTee->SetMediaTypes(spDecoderOutputMediaType.Get(), m_pOutputMediaType.Get()), done);
+ m_spObjectWrapped = spXvpTee;
spDecoderOutputMediaType = nullptr;
@@ -946,6 +983,7 @@ HRESULT CDecoderTee::ConfigDecoder(_In_ IMFTransform* pTransform, _In_ GUID guid
GUID guidMajorType;
GUID guidSubtype;
DWORD dwMediaTypeIndex = 0;
+ ComPtr<IMFDXGIDeviceManager> spDxgiManager;
UNREFERENCED_PARAMETER(guidSubType);
DMFTCHECKNULL_GOTO(pTransform, done, E_INVALIDARG);
@@ -973,12 +1011,22 @@ HRESULT CDecoderTee::ConfigDecoder(_In_ IMFTransform* pTransform, _In_ GUID guid
(void)ConfigRealTimeMFT(pTransform);
(void)pTransform->MFTGetStreamIDs(1, &m_dwMFTInputId, 1, &m_dwMFTOutputId);
- // Try to set input mediatype on MJPG decoder.
+ DMFTCHECKHR_GOTO(m_pOutputMediaType->GetMajorType(&guidMajorType), done);
+ DMFTCHECKHR_GOTO(m_pOutputMediaType->GetGUID(MF_MT_SUBTYPE, &guidSubtype), done);
+
+ if (m_spDeviceManagerUnk.Get())
+ {
+ DMFTCHECKHR_GOTO(m_spDeviceManagerUnk.As(&spDxgiManager), done);
+ if (m_D3daware && SUCCEEDED(IsDXFormatSupported(spDxgiManager.Get(), guidSubtype, nullptr, nullptr)))
+ {
+ // Set the DXGI Manager here, before the input type is set
+ DMFTCHECKHR_GOTO(pTransform->MFTProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, (ULONG_PTR)m_spDeviceManagerUnk.Get()), done);
+ }
+ }
DMFTCHECKHR_GOTO(pTransform->MFTSetInputType(m_dwMFTInputId, m_pInputMediaType.Get(), 0), done);
// Find a matching output mediatype that has the same major/Subtype as pOutputType
- DMFTCHECKHR_GOTO(m_pOutputMediaType->GetMajorType(&guidMajorType), done);
- DMFTCHECKHR_GOTO(m_pOutputMediaType->GetGUID(MF_MT_SUBTYPE, &guidSubtype), done);
+
while (SUCCEEDED(pTransform->MFTGetOutputAvailableType(m_dwMFTOutputId, dwMediaTypeIndex, &spMediaType)))
{
GUID guidMajorType2;
@@ -1061,6 +1109,18 @@ HRESULT CDecoderTee::ProcessOutputSync(_COM_Outptr_opt_ IMFSample** ppSample)
return hr;
}
+VOID CDecoderTee::ShutdownTee()
+{
+ CAutoLock lock(m_Lock);
+ SetAsyncStatus(MF_E_SHUTDOWN);
+ if (m_asyncCallback.Get())
+ {
+ // Break the circular reference between the
+ // internal async callback and the decoder
+ m_asyncCallback->Shutdown();
+ }
+}
+
#ifdef MF_DEVICEMFT_ADD_GRAYSCALER_
CGrayTee::CGrayTee(_In_ Ctee *tee) : CWrapTee(tee),m_transformfn(nullptr)
{
@@ -1174,6 +1234,122 @@ done:
}
#endif
+// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@//
+// @@@@ README: Sample copy related functions below
+//
+// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@//
+
+CSampleCopytee::CSampleCopytee(_In_ Ctee *tee, GUID category
+ , IMFVideoSampleAllocator* sampleAllocator
+) :
+ CVideoProcTee(tee, category
+ , sampleAllocator
+ )
+{
+
+}
+
+CSampleCopytee::~CSampleCopytee()
+{
+ (VOID)StopStreaming();
+ m_spDeviceManagerUnk = nullptr;
+}
+
+HRESULT CSampleCopytee::StartStreaming()
+{
+ CAutoLock lock(m_Lock);
+ RETURN_IF_FAILED(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0));
+ RETURN_IF_FAILED(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0));
+
+ return S_OK;
+}
+
+HRESULT CSampleCopytee::StopStreaming()
+{
+ CAutoLock lock(m_Lock);
+ SetAsyncStatus(MF_E_SHUTDOWN);
+ RETURN_IF_FAILED(Transform()->MFTProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, 0)); // Flush the stream
+ RETURN_IF_FAILED(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_END_OF_STREAM, 0)); // Notify end of stream
+ RETURN_IF_FAILED(Transform()->MFTProcessMessage(MFT_MESSAGE_NOTIFY_END_STREAMING, 0)); // Notify end of streaming
+
+ return S_OK;
+}
+
+STDMETHODIMP CSampleCopytee::Do(_In_ IMFSample *pSample, _Outptr_ IMFSample** ppOutSample, _Inout_ bool &newSample)
+{
+
+ HRESULT hr = S_OK;
+ MFT_OUTPUT_DATA_BUFFER outputSample;
+ ComPtr <IMFSample> spXVPOutputSample;
+ DWORD dwStatus = 0;
+ CAutoLock lock(m_Lock);
+
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Processing Sample =%p", pSample);
+ RETURN_HR_IF_NULL(E_INVALIDARG, ppOutSample);
+
+ *ppOutSample = nullptr;
+ RETURN_IF_FAILED(GetAsyncStatus());
+ RETURN_IF_FAILED(Transform()->MFTProcessInput(0, pSample, 0));
+
+ outputSample.dwStreamID = 0;
+ outputSample.pSample = NULL;
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ if (m_spDefaultAllocator)
+ {
+ RETURN_IF_FAILED(m_spDefaultAllocator->AllocateSample(&outputSample.pSample));
+ }
+ else
+#endif // ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ {
+ RETURN_IF_FAILED(m_spPrivateAllocator->AllocateSample(&outputSample.pSample));
+ }
+
+
+ hr = Transform()->MFTProcessOutput(0, 1, &outputSample, &dwStatus);
+
+ if (SUCCEEDED(hr) && pSample)
+ {
+ spXVPOutputSample.Attach(outputSample.pSample);
+ }
+ else
+ {
+ SAFE_RELEASE(outputSample.pSample);
+ }
+
+ if (spXVPOutputSample.Get())
+ {
+ newSample = true;
+ *ppOutSample = spXVPOutputSample.Detach();
+ }
+
+ return hr;
+}
+
+STDMETHODIMP CSampleCopytee::Configure(
+ _In_opt_ IMFMediaType* inMediaType,
+ _In_opt_ IMFMediaType* outMediaType,
+ _Outptr_ IMFTransform **ppTransform
+)
+{
+ RETURN_HR_IF_NULL(E_INVALIDARG, ppTransform);
+
+ CMediaTypePrinter inType(inMediaType);
+ CMediaTypePrinter outType(outMediaType);
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Input MediaType %s", inType.ToString());
+ DMFTRACE(DMFT_GENERAL, TRACE_LEVEL_INFORMATION, "%!FUNC! Output MediaType %s", outType.ToString());
+
+ RETURN_IF_FAILED(MFCreateSampleCopierMFT(ppTransform));
+ RETURN_IF_FAILED(CreateAllocator());
+
+ if (m_fSetD3DManager)
+ {
+ RETURN_IF_FAILED((*ppTransform)->MFTProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, reinterpret_cast<UINT_PTR>(m_spDeviceManagerUnk.Get())));
+ }
+
+ return S_OK;
+}
+
+
/*++
Descrtiption:
Handles events sent by the pipeline
@@ -1256,7 +1432,7 @@ HRESULT CDMFTEventHandler::KSEvent(
for (; it != m_RegularEventList.end(); it++)
{
PDMFTEventEntry pEntry = *it;
- DMFTCHECKNULL_GOTO(pEntry, done, E_FAIL);
+ DMFTCHECKNULL_GOTO(pEntry, done, E_UNEXPECTED);
if (pEntry->m_pEventData == pEventData)
{
break;
@@ -1547,7 +1723,11 @@ HRESULT CPinCreationFactory::CreatePin(_In_ ULONG ulInputStreamId, /* The Input
#if defined MF_DEVICEMFT_DECODING_MEDIATYPE_NEEDED
spOutPin = new (std::nothrow) CTranslateOutPin(ulOutStreamId, m_spDeviceTransform.Get(), spKscontrol.Get()); // Create the output pin
#else
- spOutPin = new (std::nothrow) COutPin(ulOutStreamId, m_spDeviceTransform.Get(), spKscontrol.Get()); // Create the output pin
+ spOutPin = new (std::nothrow) COutPin(ulOutStreamId, m_spDeviceTransform.Get(), spKscontrol.Get()
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ , MFSampleAllocatorUsage_DoesNotAllocate
+#endif
+ ); // Create the output pin
#endif
DMFTCHECKNULL_GOTO(spOutPin.Get(), done, E_OUTOFMEMORY);
@@ -1621,14 +1801,10 @@ done:
return hr;
}
-HRESULT CheckImagePin( _In_ IMFAttributes* pAttributes, _Out_ PBOOL pbIsImagePin )
+BOOL CheckImagePin( _In_ IMFAttributes* pAttributes, _Out_ PBOOL pbIsImagePin )
{
- if ((SUCCEEDED(CheckPinType(pAttributes, PINNAME_IMAGE, pbIsImagePin)) && pbIsImagePin) ||
- (SUCCEEDED(CheckPinType(pAttributes, PINNAME_VIDEO_STILL, pbIsImagePin)) && pbIsImagePin))
- {
- return S_OK;
- }
- return E_FAIL;
+ return ((SUCCEEDED(CheckPinType(pAttributes, PINNAME_IMAGE, pbIsImagePin)) && pbIsImagePin) ||
+ (SUCCEEDED(CheckPinType(pAttributes, PINNAME_VIDEO_STILL, pbIsImagePin)) && pbIsImagePin));
}
HRESULT CheckPreviewPin( _In_ IMFAttributes* pAttributes, _Out_ PBOOL pbIsPreviewPin)
diff --git a/avstream/sampledevicemft/multipinmfthelpers.h b/avstream/sampledevicemft/multipinmfthelpers.h
index bd3f0876..681ca071 100644
--- a/avstream/sampledevicemft/multipinmfthelpers.h
+++ b/avstream/sampledevicemft/multipinmfthelpers.h
@@ -32,9 +32,9 @@ template< typename T , HRESULT ( __stdcall T::*Func) ( IMFAsyncResult* ) >
class CDMFTAsyncCallback : public IMFAsyncCallback
{
public:
- CDMFTAsyncCallback( T* parent ) :
- m_cRef(1),
- m_Parent(parent)
+ CDMFTAsyncCallback( T* parent , DWORD dwWorkQueueId = MFASYNC_CALLBACK_QUEUE_STANDARD) :
+ m_Parent(parent),
+ m_dwQueueId(dwWorkQueueId)
{ }
virtual ~CDMFTAsyncCallback() { }
@@ -77,25 +77,40 @@ public:
STDMETHODIMP GetParameters(DWORD* pdwFlags, DWORD* pdwQueue)
{
- // Implementation of this method is optional.
- UNREFERENCED_PARAMETER(pdwFlags);
- UNREFERENCED_PARAMETER(pdwQueue);
+ *pdwFlags = 0;
+ *pdwQueue = m_dwQueueId;
return E_NOTIMPL;
}
STDMETHODIMP Invoke( IMFAsyncResult* pAsyncResult )
{
- return (m_Parent->*Func)(pAsyncResult);
+ ComPtr<T> spParent;
+ {
+ // Take a reference on the parent so that
+ // shutdown may not yank it from us
+ CAutoLock Lock(&m_Lock);
+ spParent = m_Parent;
+ }
+ if (spParent.Get())
+ {
+ return ((spParent.Get())->*Func)(pAsyncResult);
+ }
+ return MF_E_SHUTDOWN;
+ }
+ VOID Shutdown()
+ {
+ CAutoLock Lock(&m_Lock);
+ m_Parent = nullptr; //Break the reference
}
- // TODO: Implement this method.
-
T GetParent()
{
return m_Parent;
}
protected:
- T* m_Parent; // Weak reference to the parent
- long m_cRef;
+ CCritSec m_Lock;
+ ComPtr<T> m_Parent;
+ long m_cRef = 0;
+ DWORD m_dwQueueId = MFASYNC_CALLBACK_QUEUE_STANDARD;
};
@@ -107,7 +122,18 @@ public:
STDMETHODIMP_(VOID) InsertInternal ( _In_ IMFSample *pSample = nullptr );
STDMETHODIMP Insert ( _In_ IMFSample *pSample );
STDMETHODIMP Remove (_Outptr_result_maybenull_ IMFSample **pSample);
- virtual STDMETHODIMP RecreateTee ( _In_ IMFMediaType *inMediatype, _In_ IMFMediaType *outMediatype, _In_opt_ IUnknown* punkManager );
+ virtual STDMETHODIMP RecreateTee (
+ _In_ IMFMediaType *inMediatype,
+ _In_ IMFMediaType *outMediatype,
+ _In_opt_ IUnknown* punkManager);
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ STDMETHODIMP RecreateTeeByAllocatorMode(
+ _In_ IMFMediaType* inMediatype,
+ _In_ IMFMediaType* outMediatype,
+ _In_opt_ IUnknown* punkManager,
+ _In_ MFSampleAllocatorUsage allocatorUsage,
+ _In_opt_ IMFVideoSampleAllocator* pAllcoator);
+#endif
STDMETHODIMP_(VOID) Clear();
//
@@ -179,7 +205,7 @@ private:
GUID m_streamCategory;
ULONG m_cRef;
protected:
- Ctee* m_teer; /*Tee that acts as a passthrough or an XVP */
+ ComPtr<Ctee> m_spTeer; /*Tee that acts as a passthrough or an XVP */
};
@@ -197,8 +223,20 @@ public:
// The below classes are used to add the
// XVP and the Decoder components.
//
-class Ctee{
+class Ctee: public IUnknown{
public:
+ // This is a helper class to release the interface
+ // It will first call shutdowntee to break any circular
+ // references any components might have with their composed
+ // objects
+ static VOID ReleaseTee( _In_ ComPtr<Ctee> &tee)
+ {
+ if (tee)
+ {
+ tee->ShutdownTee();
+ tee = nullptr;
+ }
+ }
STDMETHOD(Start)()
{
return S_OK;
@@ -208,35 +246,85 @@ public:
return S_OK;
}
virtual STDMETHODIMP PassThrough( _In_ IMFSample * ) = 0;
+
+ STDMETHOD_(VOID, ShutdownTee)()
+ {
+ return; // NOOP
+ }
+ STDMETHODIMP QueryInterface(REFIID riid, void** ppv)
+ {
+ HRESULT hr = S_OK;
+ if (ppv != nullptr)
+ {
+ *ppv = nullptr;
+ if (riid == __uuidof(IUnknown))
+ {
+ AddRef();
+ *ppv = static_cast<IUnknown*>(this);
+ }
+ else
+ {
+ hr = E_NOINTERFACE;
+ }
+ }
+ else
+ {
+ hr = E_POINTER;
+ }
+ return hr;
+ }
+ Ctee()
+ {
+ }
+ virtual ~Ctee()
+ {}
+ STDMETHODIMP_(ULONG) AddRef()
+ {
+ return InterlockedIncrement(&m_cRef);
+ }
+ STDMETHODIMP_(ULONG) Release()
+ {
+ long cRef = InterlockedDecrement(&m_cRef);
+ if (cRef == 0)
+ {
+ delete this;
+ }
+ return cRef;
+ }
+
+protected:
+ ULONG m_cRef = 0;
};
class CNullTee:public Ctee{
public:
- CNullTee(_In_ CPinQueue* q) :m_Queue(q) {}
+ CNullTee(_In_ CPinQueue* q)
+ : m_Queue(q)
+ {
+ }
STDMETHODIMP PassThrough( _In_ IMFSample* );
+
protected:
// Store the queue here for simplicity
ComPtr<CPinQueue> m_Queue;
};
-class CWrapTee : public Ctee{
+class CWrapTee : public Ctee
+{
public:
CWrapTee( _In_ Ctee *tee=nullptr )
-: m_objectWrapped(tee)
+ : m_spObjectWrapped(tee)
, m_pInputMediaType(nullptr)
, m_pOutputMediaType(nullptr)
{
}
- virtual ~CWrapTee()=0
+ virtual ~CWrapTee()
{
- if (m_objectWrapped)
- {
- delete(m_objectWrapped);
- }
}
+
STDMETHODIMP PassThrough ( _In_ IMFSample* );
virtual STDMETHODIMP Do ( _In_ IMFSample* pSample, _Out_ IMFSample ** , _Inout_ bool &newSample) = 0;
STDMETHODIMP SetMediaTypes(_In_ IMFMediaType* pInMediaType, _In_ IMFMediaType* pOutMediaType);
@@ -262,7 +350,7 @@ protected:
ComPtr< IMFMediaType > m_pInputMediaType;
ComPtr< IMFMediaType > m_pOutputMediaType;
- Ctee *m_objectWrapped;
+ ComPtr<Ctee> m_spObjectWrapped;
};
//
@@ -272,20 +360,26 @@ class CVideoProcTee: public CWrapTee
{
public:
- CVideoProcTee( _In_ Ctee* p, _In_ GUID category = PINNAME_PREVIEW ) :CWrapTee(p)
+ CVideoProcTee( _In_ Ctee* p, _In_ GUID category = PINNAME_PREVIEW
+ , _In_ IMFVideoSampleAllocator* sampleAllocator=nullptr
+ )
+ :CWrapTee(p)
, m_bProducesSamples(FALSE)
+ , m_asyncHresult(S_OK)
, m_streamCategory(category)
, m_fSetD3DManager(FALSE)
+ , m_spDefaultAllocator(sampleAllocator)
{}
__inline IMFTransform* Transform()
{
- return m_videoProcessor.Get();
+ return m_spVideoProcessor.Get();
}
VOID SetD3DManager( _In_opt_ IUnknown* pUnk )
{
- m_spDeviceManagerUnk = pUnk;
+ m_spDeviceManagerUnk = pUnk;
}
+
STDMETHODIMP SetMediaTypes(_In_ IMFMediaType* pInMediaType, _In_ IMFMediaType* pOutMediaType);
virtual STDMETHODIMP Configure(_In_ IMFMediaType *, _In_ IMFMediaType *, _Inout_ IMFTransform**) = 0;
STDMETHOD(CreateAllocator)();
@@ -294,19 +388,33 @@ public:
HRESULT hr = S_OK;
if (SUCCEEDED(hr = StopStreaming()))
{
- if (m_objectWrapped)
+ if (m_spObjectWrapped)
{
- hr = m_objectWrapped->Stop();
+ hr = m_spObjectWrapped->Stop();
}
}
return hr;
}
+ virtual ~CVideoProcTee()
+ {}
protected:
+ CCritSec m_Lock;
+ __inline VOID SetAsyncStatus(_In_ HRESULT hrStatus)
+ {
+ InterlockedCompareExchange(&m_asyncHresult, hrStatus, S_OK);
+ }
+ HRESULT GetAsyncStatus()
+ {
+ return InterlockedCompareExchange(&m_asyncHresult, S_OK, S_OK);
+ }
STDMETHOD(StartStreaming)() = 0;
STDMETHOD(StopStreaming)() = 0;
- ComPtr< IMFTransform > m_videoProcessor;
+ HRESULT m_asyncHresult;
+ ComPtr< IMFTransform > m_spVideoProcessor;
ComPtr<IUnknown> m_spDeviceManagerUnk;
- ComPtr<IMFVideoSampleAllocatorEx> m_spAllocator;
+ ComPtr<IMFVideoSampleAllocatorEx> m_spPrivateAllocator;
+ ComPtr<IMFVideoSampleAllocator> m_spDefaultAllocator;
+
BOOL m_bProducesSamples;
GUID m_streamCategory;
BOOL m_fSetD3DManager;
@@ -315,11 +423,12 @@ protected:
class CXvptee :public CVideoProcTee{
public:
CXvptee( _In_ Ctee *, _In_ GUID category = PINNAME_PREVIEW );
- ~CXvptee();
+ virtual ~CXvptee();
STDMETHOD(StartStreaming)();
STDMETHOD(StopStreaming)();
STDMETHODIMP Do ( _In_ IMFSample* pSample, _Outptr_ IMFSample **, _Inout_ bool &newSample);
STDMETHODIMP Configure ( _In_opt_ IMFMediaType *, _In_opt_ IMFMediaType *, _Outptr_ IMFTransform** );
+
};
class CDecoderTee : public CVideoProcTee {
@@ -338,23 +447,11 @@ public:
, m_dwMFTInputId(0)
, m_dwMFTOutputId(0)
, m_dwQueueId(dwQueueId)
- ,m_dwCameraStreamWorkQueueId(0)
- , m_ulProcessOutputsInFlight(0)
- , m_hSyncHandle(INVALID_HANDLE_VALUE)
- , m_StoppedAndWaiting(FALSE)
+ , m_dwCameraStreamWorkQueueId(0)
{
m_streamCategory = category;
}
- ~CDecoderTee();
-
- __inline VOID SetAsyncStatus( _In_ HRESULT hrStatus )
- {
- InterlockedCompareExchange(&m_asyncHresult, hrStatus, S_OK);
- }
- HRESULT GetAsyncStatus()
- {
- return InterlockedCompareExchange(&m_asyncHresult, S_OK, S_OK);
- }
+ virtual ~CDecoderTee();
STDMETHODIMP Do(_In_ IMFSample* pSample, _Outptr_ IMFSample **, _Inout_ bool &newSample);
STDMETHODIMP Configure(_In_opt_ IMFMediaType *, _In_opt_ IMFMediaType *, _Outptr_ IMFTransform**);
@@ -362,16 +459,17 @@ public:
protected:
STDMETHODIMP StartStreaming();
STDMETHODIMP StopStreaming();
- _Ret_maybenull_ HRESULT CDecoderTee::GetSample( _Outptr_ IMFSample**);
+ HRESULT GetSample( _Outptr_result_maybenull_ IMFSample**);
HRESULT ConfigDecoder( _In_ IMFTransform* ,_In_ GUID guidSubType = GUID_NULL);
HRESULT ConfigRealTimeMFT(_In_ IMFTransform* );
HRESULT ProcessOutputSync( _COM_Outptr_opt_ IMFSample** );
HRESULT ProcessFormatChange();
+ STDMETHOD_(VOID, ShutdownTee)();
BOOL m_fAsyncMFT;
BOOL m_D3daware;
BOOL m_hwMFT;
- ComPtr<CDMFTAsyncCallback<CDecoderTee,&CDecoderTee::Invoke> > m_asyncCallback;
+ ComPtr<CDMFTAsyncCallback<CDecoderTee, &CDecoderTee::Invoke> > m_asyncCallback;
HRESULT m_asyncHresult;
DWORD m_lNeedInputRequest;
GUID m_streamCategory; // Needed for bind flags
@@ -381,14 +479,22 @@ protected:
ComPtr<IMFSample> m_spUnprocessedSample;
DWORD m_dwQueueId;
DWORD m_dwCameraStreamWorkQueueId;
- CCritSec m_critSec;
std::deque<ComPtr<IMFSample> > m_InputSampleList;
- ULONG m_ulProcessOutputsInFlight;
- HANDLE m_hSyncHandle;
- BOOL m_StoppedAndWaiting;
};
+class CSampleCopytee :public CVideoProcTee {
+public:
+ CSampleCopytee(_In_ Ctee*, _In_ GUID category = PINNAME_PREVIEW
+ , _In_ IMFVideoSampleAllocator* sampleAllocator = nullptr
+ );
+ ~CSampleCopytee();
+ STDMETHOD(StartStreaming)();
+ STDMETHOD(StopStreaming)();
+ STDMETHODIMP Do(_In_ IMFSample* pSample, _Outptr_ IMFSample **, _Inout_ bool &newSample);
+ STDMETHODIMP Configure(_In_opt_ IMFMediaType *, _In_opt_ IMFMediaType *, _Outptr_ IMFTransform**);
+};
+
#ifdef MF_DEVICEMFT_ADD_GRAYSCALER_
class CGrayTee : public CWrapTee {
public:
@@ -499,6 +605,7 @@ public:
DMFT_PIN_INPUT,
DMFT_PIN_OUTPUT,
DMFT_PIN_CUSTOM,
+ DMFT_PIN_ALLOCATOR_PIN,
DMFT_MAX
}type_pin;
HRESULT CreatePin( _In_ ULONG ulInputStreamId, _In_ ULONG ulOutStreamId, _In_ type_pin type,_Outptr_ CBasePin** ppPin, _In_ BOOL& isCustom);
@@ -506,7 +613,7 @@ public:
}
};
HRESULT CheckPinType(_In_ IMFAttributes* pAttributes, _In_ GUID pinType, _Out_ PBOOL pbIsImagePin);
-HRESULT CheckImagePin(_In_ IMFAttributes* pAttributes, _Out_ PBOOL pbIsImagePin);
+BOOL CheckImagePin(_In_ IMFAttributes* pAttributes, _Out_ PBOOL pbIsImagePin);
HRESULT CheckPreviewPin(_In_ IMFAttributes* pAttributes, _Out_ PBOOL pbIsPreviewPin);
diff --git a/avstream/sampledevicemft/multipinmftutils.cpp b/avstream/sampledevicemft/multipinmftutils.cpp
index d056b364..e4a62d52 100644
--- a/avstream/sampledevicemft/multipinmftutils.cpp
+++ b/avstream/sampledevicemft/multipinmftutils.cpp
@@ -1301,6 +1301,83 @@ done:
const UINT32 ALLOCATOR_MIN_SAMPLES = 10;
const UINT32 ALLOCATOR_MAX_SAMPLES = 50;
+
+HRESULT ConfigureAllocator(
+ _In_ IMFMediaType* pOutputMediaType,
+ _In_ GUID streamCategory,
+ _In_ IUnknown* pDeviceManagerUnk,
+ _In_ BOOL &bDxAllocator,
+ _In_ IMFVideoSampleAllocator* pAllocator)
+{
+ HRESULT hr = S_OK;
+ wil::com_ptr_nothrow<IMFVideoSampleAllocatorEx> spPrivateAllocator;
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ wil::com_ptr_nothrow<IMFVideoCaptureSampleAllocator> spDefaultAllocator;
+#endif
+ wil::com_ptr_nothrow<IMFAttributes> spAllocatorAttributes;
+ GUID guidMajorType = GUID_NULL;
+ GUID guidSubtype = GUID_NULL;
+ BOOL fDXAllocator = FALSE;
+
+ RETURN_HR_IF_NULL(E_INVALIDARG, pAllocator );
+ RETURN_HR_IF_NULL(E_INVALIDARG, pOutputMediaType );
+
+ RETURN_IF_FAILED(pOutputMediaType->GetMajorType(&guidMajorType));
+
+ if (!IsEqualGUID(guidMajorType, MFMediaType_Video))
+ {
+ RETURN_HR(MF_E_INVALIDMEDIATYPE);
+ }
+
+ RETURN_IF_FAILED(pOutputMediaType->GetGUID(MF_MT_SUBTYPE, &guidSubtype));
+ //
+ // Set Attributes on the allocator we need. First get the Bind Flags.
+ //
+ RETURN_IF_FAILED(MFCreateAttributes(&spAllocatorAttributes, 8));
+ RETURN_IF_FAILED(spAllocatorAttributes->SetUINT32(MF_SA_BUFFERS_PER_SAMPLE, 1));
+
+ if (pDeviceManagerUnk != nullptr)
+ {
+ if (SUCCEEDED(UpdateAllocatorAttributes(spAllocatorAttributes.get(), streamCategory, guidSubtype, (IMFDXGIDeviceManager*)pDeviceManagerUnk)))
+ {
+ fDXAllocator = TRUE;
+ }
+ }
+
+ if (fDXAllocator)
+ {
+ RETURN_IF_FAILED(pAllocator->SetDirectXManager(pDeviceManagerUnk));
+ }
+
+ if (SUCCEEDED(pAllocator->QueryInterface(IID_PPV_ARGS(&spPrivateAllocator))))
+ {
+ RETURN_IF_FAILED(spPrivateAllocator->InitializeSampleAllocatorEx(
+ ALLOCATOR_MIN_SAMPLES,
+ ALLOCATOR_MAX_SAMPLES,
+ spAllocatorAttributes.get(),
+ pOutputMediaType));
+ }
+#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB))
+ else if (SUCCEEDED(pAllocator->QueryInterface(IID_PPV_ARGS(&spDefaultAllocator))))
+ {
+ RETURN_IF_FAILED(spDefaultAllocator->InitializeCaptureSampleAllocator(
+ 0, /*use sample size by MediaType*/
+ 0, /*metadata size*/
+ 0, /*default alignment*/
+ ALLOCATOR_MIN_SAMPLES,
+ spAllocatorAttributes.get(),
+ pOutputMediaType));
+ }
+#endif
+ else
+ {
+ hr = E_INVALIDARG;
+ }
+
+ bDxAllocator = fDXAllocator;
+
+ return hr;
+}
//
//@@@@ README: Creating an Allocator.. Please don't allocate samples individually using MFCreateSample as that can lead to fragmentation and is
// extremely inefficent. Instead create an Allocator which will create a fixed number of samples which are recycled when the pipeline returns back
@@ -1337,7 +1414,7 @@ HRESULT CreateAllocator( _In_ IMFMediaType* pOutputMediaType,
DMFTCHECKHR_GOTO(MFCreateAttributes(&spAllocatorAttributes, 8), done);
DMFTCHECKHR_GOTO(spAllocatorAttributes->SetUINT32(MF_SA_BUFFERS_PER_SAMPLE, 1), done);
- if (pDeviceManagerUnk != nullptr)
+ if (pDeviceManagerUnk != nullptr)
{
if (SUCCEEDED(UpdateAllocatorAttributes(spAllocatorAttributes.Get(), streamCategory,guidSubtype, (IMFDXGIDeviceManager*)pDeviceManagerUnk)))
{
@@ -1349,6 +1426,7 @@ HRESULT CreateAllocator( _In_ IMFMediaType* pOutputMediaType,
{
DMFTCHECKHR_GOTO(spVideoSampleAllocator->SetDirectXManager(pDeviceManagerUnk), done);
}
+
DMFTCHECKHR_GOTO(spVideoSampleAllocator->InitializeSampleAllocatorEx(ALLOCATOR_MIN_SAMPLES, ALLOCATOR_MAX_SAMPLES, spAllocatorAttributes.Get(), pOutputMediaType), done);
*ppAllocator = spVideoSampleAllocator.Detach();
@@ -1487,16 +1565,16 @@ done:
HRESULT MergeSampleAttributes( _In_ IMFSample* pInSample, _Inout_ IMFSample* pOutSample)
{
HRESULT hr = S_OK;
- DMFTCHECKNULL_GOTO(pInSample, done, E_INVALIDARG);
- DMFTCHECKNULL_GOTO(pOutSample, done, E_INVALIDARG);
UINT32 cAttributes = 0;
GUID guidAttribute;
PROPVARIANT varAttribute;
PROPVARIANT varAttributeExists;
-
PropVariantInit(&varAttribute);
PropVariantInit(&varAttributeExists);
+ DMFTCHECKNULL_GOTO(pInSample, done, E_INVALIDARG);
+ DMFTCHECKNULL_GOTO(pOutSample, done, E_INVALIDARG);
+
DMFTCHECKHR_GOTO(pInSample->GetCount(&cAttributes), done);
for (UINT32 i = 0; i < cAttributes; i++)
{
diff --git a/avstream/sampledevicemft/packages.config b/avstream/sampledevicemft/packages.config
new file mode 100644
index 00000000..09cb1163
--- /dev/null
+++ b/avstream/sampledevicemft/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="Microsoft.Windows.ImplementationLibrary" version="1.0.190716.2" targetFramework="native" />
+</packages> \ No newline at end of file
diff --git a/avstream/sampledevicemft/stdafx.h b/avstream/sampledevicemft/stdafx.h
index e2f5a6cd..657208cd 100644
--- a/avstream/sampledevicemft/stdafx.h
+++ b/avstream/sampledevicemft/stdafx.h
@@ -41,6 +41,11 @@ using namespace std;
using namespace ABI::Windows::Foundation;
using namespace Microsoft::WRL;
+#include <wil\result.h>
+#include <wil\resource.h>
+#include <wil\com.h>
+#include <wil\result_macros.h>
+
// @@@@ README Please check / uncheck various hash defines to enable/ disable features
// MF_DEVICEMFT_ASYNCPIN_NEEDED will show how to use Asynchronous queues
// MF_DEVICEMFT_DECODING_MEDIATYPE_NEEDED will show how to decode a compressed mediatype.. it supports H264 and MJPG
@@ -49,7 +54,7 @@ using namespace Microsoft::WRL;
//
//#define MF_DEVICEMFT_ADD_GRAYSCALER_ 1
#define MF_DEVICEMFT_ASYNCPIN_NEEDED 1
-#define MF_DEVICEMFT_DECODING_MEDIATYPE_NEEDED 1
+//#define MF_DEVICEMFT_DECODING_MEDIATYPE_NEEDED 0
#define MF_DEVICEMFT_SET_SPHERICAL_ATTRIBUTES 1
//#define MF_DEVICEMFT_ENUM_HW_DECODERS 1