From 1d2865d33a2815c31a93bf9b352b94b096f72f57 Mon Sep 17 00:00:00 2001 From: Joel Corley Date: Tue, 21 Jan 2020 15:47:24 -0800 Subject: Update all the AvStream samples for Vibranium. --- avstream/avscamera/Package/package.VcxProj | 4 - avstream/avscamera/README.md | 30 +- avstream/avscamera/mft0/AvsCameraMft0.vcxproj | 12 +- avstream/avscamera/mft0/MFT0Impl.cpp | 4 +- avstream/avscamera/mft0/stdafx.h | 5 + avstream/avscamera/sys/AvsCamera.vcxproj | 4 +- avstream/avscamera/sys/AvsCameraFilter.cpp | 11 +- avstream/avscamera/sys/Capture.cpp | 11 + avstream/avscamera/sys/Common.h | 7 +- avstream/avscamera/sys/Device.cpp | 24 +- avstream/avscamera/sys/Device.h | 13 +- avstream/avscamera/sys/PreviewHwSim.cpp | 32 +- avstream/avscamera/sys/PreviewHwSim.h | 4 +- avstream/avscamera/sys/Sensor.cpp | 49 +-- avstream/avscamera/sys/Sensor.h | 15 +- avstream/avscamera/sys/SensorSimulation.cpp | 82 +++++ avstream/avscamera/sys/SensorSimulation.h | 8 +- avstream/avscamera/sys/VideoHwSim.cpp | 49 +++ avstream/avscamera/sys/VideoHwSim.h | 4 + avstream/avscamera/sys/avscamera.inf | Bin 26816 -> 0 bytes avstream/avscamera/sys/avscamera.inx | Bin 0 -> 25260 bytes avstream/avscamera/sys/filter.cpp | 183 ++++++++-- avstream/avscamera/sys/filter.h | 8 +- avstream/avscamera/sys/hwsim.cpp | 46 +-- avstream/avscamera/sys/imagecapture.cpp | 4 +- avstream/avshws/README.md | 108 +++--- avstream/avshws/avshws.inf | 173 --------- avstream/avshws/avshws.inx | Bin 0 -> 5944 bytes avstream/avshws/avshws.sln | 5 +- avstream/avshws/avshws.vcxproj | 4 +- avstream/avshws/makefile | 15 + avstream/avssamp/README.md | 87 +++-- avstream/avssamp/audio.cpp | 2 +- avstream/avssamp/avssamp.inf | 93 ----- avstream/avssamp/avssamp.inx | Bin 0 -> 3226 bytes avstream/avssamp/avssamp.vcxproj | 2 +- avstream/avssamp/makefile | 15 + avstream/sampledevicemft/basepin.cpp | 171 ++++++--- avstream/sampledevicemft/basepin.h | 64 +++- avstream/sampledevicemft/common.h | 11 +- avstream/sampledevicemft/contosodevice.h | 28 ++ avstream/sampledevicemft/custompin.cpp | 2 +- avstream/sampledevicemft/dllmain.cpp | 24 +- avstream/sampledevicemft/multipinmft.cpp | 60 +++- avstream/sampledevicemft/multipinmft.h | 20 +- avstream/sampledevicemft/multipinmft.vcxproj | 8 + .../sampledevicemft/multipinmft.vcxproj.Filters | 1 + avstream/sampledevicemft/multipinmfthelpers.cpp | 396 +++++++++++++++------ avstream/sampledevicemft/multipinmfthelpers.h | 211 ++++++++--- avstream/sampledevicemft/multipinmftutils.cpp | 86 ++++- avstream/sampledevicemft/stdafx.h | 7 +- avstream/samplemft0/README.md | 48 ++- 52 files changed, 1496 insertions(+), 754 deletions(-) delete mode 100644 avstream/avscamera/sys/avscamera.inf create mode 100644 avstream/avscamera/sys/avscamera.inx delete mode 100644 avstream/avshws/avshws.inf create mode 100644 avstream/avshws/avshws.inx create mode 100644 avstream/avshws/makefile delete mode 100644 avstream/avssamp/avssamp.inf create mode 100644 avstream/avssamp/avssamp.inx create mode 100644 avstream/avssamp/makefile create mode 100644 avstream/sampledevicemft/contosodevice.h 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 @@ Windows10 true - Universal Windows10 false - Universal Windows10 true - Universal Windows10 false - Universal diff --git a/avstream/avscamera/README.md b/avstream/avscamera/README.md index da8e8d65..ef956c88 100644 --- a/avstream/avscamera/README.md +++ b/avstream/avscamera/README.md @@ -1,26 +1,22 @@ ---- -page_type: sample -description: "Provides a pin-centric AVStream capture driver for a simulated front and back camera that performs simulated captures." -urlFragment: avscamera -languages: -- cpp -products: -- windows -- windows-wdk ---- - -# AvsCamera - AVStream Camera Sample Driver - -The AvsCamera sample provides a pin-centric AVStream capture driver for a simulated front and back camera. The driver performs simulated captures at 320x240 or 640x480 in RGB24, RGB32, YUY2 and NV12 formats at various frame rates. The purpose of the sample is to demonstrate how to write a fully functional AVStream camera driver. + + +AvsCamera: AVStream Camera Sample Driver +======================================== +The AvsCamera sample provides a pin-centric AVStream capture driver for a simulated front and back camera. The driver performs simulated captures at 320x240 or 640x480 in RGB24, RGB32, YUY2 and NV12 formats at various frame rates. The purpose of the sample is to demonstrate how to write a fully functional AVStream camera driver. This sample features strong parameter validation and overflow detection. It provides validation and simulation logic for all advanced camera controls in the CCaptureFilter class. A real camera driver would replace the filter automation table and CSensor and CSynthesizer class hierarchies to produce a new camera driver. The sample comes with its own MFT0 called AvsCameraMft0.dll. This MFT0 is used to parse metadata supplied in the AvsCamera driver samples. The metadata communications from the driver is primarily a private channel to its MFT0. The MFT0 is responsible for reformatting that information for the capture pipeline. ## Universal Windows Driver Compliant - This sample builds a Universal Windows Driver. It uses only APIs and DDIs that are included in OneCoreUAP. The sample works on 32-bit and 64-bit x86, amd64 and arm platforms. Once installed, the simulated camera should show in the Windows Inbox camera app. ## Building the sample - -The AvsCamera sample can be built by opening the AvsCamera.sln solution file. A successful build produces AvsCamera.sys, AvsCameraMft0.dll, AvsCamera.inf and AvsCamera.cat. +The AvsCamera sample can be built by opening the AvsCamera.sln solution file. A successful build produces AvsCamera.sys, AvsCameraMft0.dll, AvsCamera.inf and AvsCamera.cat. diff --git a/avstream/avscamera/mft0/AvsCameraMft0.vcxproj b/avstream/avscamera/mft0/AvsCameraMft0.vcxproj index 518a324f..1c59ed8f 100644 --- a/avstream/avscamera/mft0/AvsCameraMft0.vcxproj +++ b/avstream/avscamera/mft0/AvsCameraMft0.vcxproj @@ -31,7 +31,7 @@ Windows10 False - Universal + Desktop WindowsApplicationForDrivers10.0 DynamicLibrary @@ -39,7 +39,7 @@ Windows10 True - Universal + Desktop WindowsApplicationForDrivers10.0 DynamicLibrary @@ -47,7 +47,7 @@ Windows10 False - Universal + Desktop WindowsApplicationForDrivers10.0 DynamicLibrary @@ -55,7 +55,7 @@ Windows10 True - Universal + Desktop WindowsApplicationForDrivers10.0 DynamicLibrary @@ -201,7 +201,7 @@ - + @@ -213,4 +213,4 @@ - \ No newline at end of file + 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.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 @@ - + @@ -244,4 +244,4 @@ - \ No newline at end of file + 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..aadaca4e 100644 --- a/avstream/avscamera/sys/Capture.cpp +++ b/avstream/avscamera/sys/Capture.cpp @@ -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..d29a0438 100644 --- a/avstream/avscamera/sys/Common.h +++ b/avstream/avscamera/sys/Common.h @@ -23,12 +23,17 @@ #define _NO_SYS_GUID_OPERATOR_EQ_ +#ifdef NTDDI_VERSION +#undef NTDDI_VERSION +#endif //NTDDI_VERSION +#define NTDDI_VERSION NTDDI_WIN10_VB + #include #include #include -#include #include +//#include #include #include #include diff --git a/avstream/avscamera/sys/Device.cpp b/avstream/avscamera/sys/Device.cpp index 99bc60ce..9fab69d9 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,17 @@ Return Value: sizeof(pld), (PVOID)&pld) ); + + //Also set Panel ID manually, because PnP does not do this for the interface currently + // TODO: This is a bug in PnP that they will fix, so don't check the return code + // It will be read only when fixed. + 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..1f062497 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 muck with 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..c68f1b3a 100644 --- a/avstream/avscamera/sys/Sensor.h +++ b/avstream/avscamera/sys/Sensor.h @@ -517,8 +517,19 @@ 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 +565,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 +588,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.inf deleted file mode 100644 index 2a17a764..00000000 Binary files a/avstream/avscamera/sys/avscamera.inf and /dev/null differ diff --git a/avstream/avscamera/sys/avscamera.inx b/avstream/avscamera/sys/avscamera.inx new file mode 100644 index 00000000..f6f1e846 Binary files /dev/null and b/avstream/avscamera/sys/avscamera.inx 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; iGetPinCount(); 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..07f1c0d4 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..109bc968 100644 --- a/avstream/avshws/README.md +++ b/avstream/avshws/README.md @@ -1,86 +1,96 @@ ---- -page_type: sample -description: "A simulated hardware sample driver providing a pin-centric capture driver to simulate AV capture hardware." -languages: -- cpp -products: -- windows -- windows-wdk ---- + -# AVStream simulated hardware sample driver (Avshws) +AVStream simulated hardware sample driver (Avshws) +================================================== -The AVStream simulated hardware sample driver (Avshws) provides a pin-centric [AVStream](https://docs.microsoft.com/windows-hardware/drivers/stream/avstream-overview) capture driver for a simulated piece of hardware. This streaming media driver performs video captures at 320 x 240 pixels in either RGB24 or YUV422 format using direct memory access (DMA) into capture buffers. The purpose of the sample is to demonstrate how to write a pin-centric AVStream minidriver. The sample also shows how to implement DMA by using the related functionality provided by the AVStream class driver. +The AVStream simulated hardware sample driver (Avshws) provides a pin-centric [AVStream](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554240) capture driver for a simulated piece of hardware. This streaming media driver performs video captures at 320 x 240 pixels in either RGB24 or YUV422 format using direct memory access (DMA) into capture buffers. The purpose of the sample is to demonstrate how to write a pin-centric AVStream minidriver. The sample also shows how to implement DMA by using the related functionality provided by the AVStream class driver. This sample features enhanced parameter validation and overflow detection. -## Provision a target computer +Provision a target computer +--------------------------- After you've installed the sample on your host computer, run Visual Studio, and from the **File** menu, select **Open**, then **Project/Solution...**, navigate to the directory where you've copied the Avshws sample, then to the C++ folder, and select **avshws.vcxproj** (the VC++ Project). -In the **Solution Explorer** pane in Visual Studio, at the top is **Solution 'avshws'**. Right-click this and select **Configuration Manager**. Follow the instructions in [Building a Driver with Visual Studio and the WDK](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver) to set the platform, operating system, and debug configuration you want to use, and to build the sample. This sample project will automatically sign the driver package. +In the **Solution Explorer** pane in Visual Studio, at the top is **Solution 'avshws'**. Right-click this and select **Configuration Manager**. Follow the instructions in [Building a Driver with the WDK](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644) to set the platform, operating system, and debug configuration you want to use, and to build the sample. This sample project will automatically sign the driver package. -Provision your target computer using instructions in, for example, [Provision a computer for driver deployment and testing](https://docs.microsoft.com/windows-hardware/drivers/gettingstarted/provision-a-target-computer-wdk-8-1). Ensure that in the **Network and Sharing Center** control panel your target computer has **Network Discovery** and **File and Printer Sharing** enabled. +Provision your target computer using instructions in, for example, [Preparing a Computer for Provisioning](http://msdn.microsoft.com/en-us/library/windows/hardware/dn265573). Ensure that in the **Network and Sharing Center** control panel your target computer has **Network Discovery** and **File and Printer Sharing** enabled. -## Deploy the driver to the target computer +Deploy the driver to the target computer +---------------------------------------- -Now you can deploy the Avshws driver that you've just built to the target computer, using guidance in [Deploying a Driver to a Test Computer](https://docs.microsoft.com/windows-hardware/drivers/develop/deploying-a-driver-to-a-test-computer). Specifically, find the package file under the **Package** folder in the Avshws solution. Right-click **package** and select **Properties**. Under Configuration Properties, click **Driver install** and then **Deployment**. Here you must click the check box for **Enable deployment**, and then click the button to the right of **\**. In the next dialog you enter the **Target Computer Name** and can let the host computer automatically provision the target computer and set up debugger options. +Now you can deploy the Avshws driver that you've just built to the target computer, using guidance in [Deploying a Driver to a Test Computer](http://msdn.microsoft.com/en-us/library/windows/hardware/hh454834). Specifically, find the package file under the **Package** folder in the Avshws solution. Right-click **package** and select **Properties**. Under Configuration Properties, click **Driver install** and then **Deployment**. Here you must click the check box for **Enable deployment**, and then click the button to the right of **\**. In the next dialog you enter the **Target Computer Name** and can let the host computer automatically provision the target computer and set up debugger options. Finally, in Visual Studio, from the **Build** menu select **Deploy Solution** to deploy the sample to the target computer. On the target computer, you can see the deployed package in the **%Systemdrive%\\drivertest\\drivers** folder. -## Install the driver +Install the driver +------------------ On the target computer, open Device Manager, and follow these steps: -1. In the **Action** menu, click **Add Legacy Hardware**, and the **Add Hardware Wizard** appears. Click **Next** and then **Next** again. - -1. In the **Add Hardware** window, select **Show All Devices**. - -1. In the **Manufacturer** list in the left pane, click **Microsoft**. - -1. You should see the **AVStream Simulated Hardware Sample** in the **Model** pane on the right. Click this and then click **Next**. - -1. Click **Next** again to install the driver, and then click **Finish** to exit the wizard. +1. In the **Action** menu, click **Add Legacy Hardware**, and the **Add Hardware Wizard** appears. Click **Next** and then **Next** again. +2. In the **Add Hardware** window, select **Show All Devices**. +3. In the **Manufacturer** list in the left pane, click **Microsoft**. +4. You should see the **AVStream Simulated Hardware Sample** in the **Model** pane on the right. Click this and then click **Next**. +5. Click **Next** again to install the driver, and then click **Finish** to exit the wizard. The sample driver now appears in the Device Manager console tree under **Sound, video and game controllers**. The Avshws INF file will be on the system drive at, for example, **...windows\\System32\\DriverStore\\FileRepository\\**. -## Sample code hierarchy +Sample code hierarchy +--------------------- -[**DriverEntry**](https://docs.microsoft.com/previous-versions//ff558717(v=vs.85)) in Device.cpp is the initial point of entry into the driver. This routine passes control to AVStream by calling the [**KsInitializeDriver**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/nf-ks-ksinitializedriver) function. In this call, the minidriver passes the device descriptor, an AVStream structure that recursively defines the AVStream object hierarchy for a driver. This is common behavior for an AVStream minidriver. +[**DriverEntry**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff558717) in Device.cpp is the initial point of entry into the driver. This routine passes control to AVStream by calling the [**KsInitializeDriver**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff562683) function. In this call, the minidriver passes the device descriptor, an AVStream structure that recursively defines the AVStream object hierarchy for a driver. This is common behavior for an AVStream minidriver. -At device start time, a simulated piece of capture hardware is created (the **CHardwareSimulation** class), and a DMA adapter is acquired from the operating system and is registered with AVStream by calling the [**KsDeviceRegisterAdapterObject**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/nf-ks-ksdeviceregisteradapterobject) function. This call is required for a sample that performs DMA access directly into the capture buffers, instead of using DMA access to write to a common buffer. The driver creates the [KS Filter](https://docs.microsoft.com/windows-hardware/drivers/stream/ks-filters) for this device dynamically by calling the [**KsCreateFilterFactory**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/nf-ks-kscreatefilterfactory) function. +At device start time, a simulated piece of capture hardware is created (the **CHardwareSimulation** class), and a DMA adapter is acquired from the operating system and is registered with AVStream by calling the [**KsDeviceRegisterAdapterObject**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff561687) function. This call is required for a sample that performs DMA access directly into the capture buffers, instead of using DMA access to write to a common buffer. The driver creates the [KS Filter](http://msdn.microsoft.com/en-us/library/windows/hardware/ff567644) for this device dynamically by calling the [**KsCreateFilterFactory**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff561650) function. -Filter.cpp is where the sample lays out the [**KSPIN\_DESCRIPTOR\_EX**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/ns-ks-_kspin_descriptor_ex) structure for the single video pin. In addition, a [**KSFILTER\_DISPATCH**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/ns-ks-_ksfilter_dispatch) structure and a [**KSFILTER\_DESCRIPTOR**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/ns-ks-_ksfilter_descriptor) structure are provided in this source file. The filter dispatch provides only a create dispatch, a routine that is included in Filter.cpp. The process dispatch is provided on the pin because this is a pin-centric sample. +Filter.cpp is where the sample lays out the [**KSPIN\_DESCRIPTOR\_EX**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff563534) structure for the single video pin. In addition, a [**KSFILTER\_DISPATCH**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff562554) structure and a [**KSFILTER\_DESCRIPTOR**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff562553) structure are provided in this source file. The filter dispatch provides only a create dispatch, a routine that is included in Filter.cpp. The process dispatch is provided on the pin because this is a pin-centric sample. -Capture.cpp contains source for the video capture pin on the capture filter. This is where the [**KSPIN\_DISPATCH**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/ns-ks-_kspin_dispatch) structure for the unique pin is provided. This dispatch structure specifies a *Process* callback routine, also defined in this source file. This routine is where stream pointer manipulation and cloning occurs. +Capture.cpp contains source for the video capture pin on the capture filter. This is where the [**KSPIN\_DISPATCH**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff563535) structure for the unique pin is provided. This dispatch structure specifies a *Process* callback routine, also defined in this source file. This routine is where stream pointer manipulation and cloning occurs. The process callback is one of two routines of interest in Capture.cpp that demonstrate how to perform DMA transfers with AVStream functionality. The other is the **CCapturePin::CompleteMappings** method. These two methods show how to use the queue, obtain clone pointers, use scatter/gather lists, and perform other DMA-related tasks. For more information, see the comments in all .cpp files. -## Run the sample +Run the sample +-------------- Follow these steps to see how the sample driver functions: -1. After installation has completed, access the driver through the Graphedt tool. Graphedt.exe is available in the *tools* directory of the WDK. - -1. Before running GraphEdit, use the regsvr32 utility to register the proppage.dll DLL and to enable GraphEdit to display property pages for some of the built-in Microsoft DirectShow filters. Open an elevated command window with Administrator privileges, and navigate to the WDK or SDK *tools* directory that contains proppage.dll. - -1. On the command line, type regsvr32 proppage.dll. If the registration succeeds, you'll get a message, "DllRegisterServer in proppage.dll succeeded." Click OK. - -1. In the Graphedt tool, click the **Graph** menu and click **Insert Filters**. The sample appears under "WDM Streaming Capture Devices" as "avshws Source." - -1. Click **Insert Filter**. The sample appears in the graph as a single filter labeled, "avshws Source." There is one output pin, which is the video capture pin. This pin emits video in YUY2 format. - -1. Attach this filter to either a DirectShow Video Renderer or to the VMR default video renderer. Then click **Play**. +1. After installation has completed, access the driver through the Graphedt tool. Graphedt.exe is available in the *tools* directory of the WDK. +2. Before running GraphEdit, use the regsvr32 utility to register the proppage.dll DLL and to enable GraphEdit to display property pages for some of the built-in Microsoft DirectShow filters. Open an elevated command window with Administrator privileges, and navigate to the WDK or SDK *tools* directory that contains proppage.dll. +3. On the command line, type regsvr32 proppage.dll. If the registration succeeds, you'll get a message, "DllRegisterServer in proppage.dll succeeded." Click OK. +4. In the Graphedt tool, click the **Graph** menu and click **Insert Filters**. The sample appears under "WDM Streaming Capture Devices" as "avshws Source." +5. Click **Insert Filter**. The sample appears in the graph as a single filter labeled, "avshws Source." There is one output pin, which is the video capture pin. This pin emits video in YUY2 format. +6. Attach this filter to either a DirectShow Video Renderer or to the VMR default video renderer. Then click **Play**. The output that is produced by the sample is a 320 x 240 pixel image of standard EIA-189-A color bars. In the middle of the image near the bottom, a clock appears over the image. This clock displays the elapsed time since the graph was introduced into the run state following the last stop. The clock display format is MINUTES:SECONDS.HUNDREDTHS. In the upper-left corner of the image, a counter counts the number of frames that have been dropped since the graph was introduced into the run state after the last stop. -## File manifest - -| File | Description | -| --- | --- | -| Avshws.h | Main header file for the sample | -| Avshws.inf | Sample installation file | +Code tour +--------- + +### File Manifest + +File | Description +-----|------------ +Avshws.h | Main header file for the sample. +Avshws.inx | Template installation file from which an architecture specific INF file is generated on build. +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 Binary files /dev/null and b/avstream/avshws/avshws.inx 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 @@ - + @@ -331,4 +331,4 @@ - \ No newline at end of file + 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/README.md b/avstream/avssamp/README.md index 42f0d393..44a44139 100644 --- a/avstream/avssamp/README.md +++ b/avstream/avssamp/README.md @@ -1,58 +1,57 @@ ---- -page_type: sample -description: "An AVStream filter-centric simulated capture sample driver with functional audio." -languages: -- cpp -products: -- windows -- windows-wdk ---- + -# AVStream filter-centric simulated capture sample driver (Avssamp) +AVStream filter-centric simulated capture sample driver (Avssamp) +================================================================= -The AVStream filter-centric simulated capture sample driver (Avssamp) provides a filter-centric [AVStream](https://docs.microsoft.com/windows-hardware/drivers/stream/avstream-overview) capture driver with functional audio. This streaming media driver performs video captures at 320 x 240 pixel resolution in RGB24 or YUV422 format while playing a user-provided Pulse Code Modulation (PCM) wave audio file in a loop. The sample demonstrates how to write a filter-centric AVStream minidriver. +The AVStream filter-centric simulated capture sample driver (Avssamp) provides a filter-centric [AVStream](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554240) capture driver with functional audio. This streaming media driver performs video captures at 320 x 240 pixel resolution in RGB24 or YUV422 format while playing a user-provided Pulse Code Modulation (PCM) wave audio file in a loop. The sample demonstrates how to write a filter-centric AVStream minidriver. -## Installation instructions -1. Copy AVssamp.inf to a directory, for example, C:\\Avstream\\. - -1. In this directory, create a new subdirectory named objfre\_x86 if the target operating system is x86-based, or objfre\_amd64 for an x64-based target operating system, for example, C:\\AVstream\\objfre\_x86\\. - -1. Copy the processor-appropriate Avssamp.sys file to the objfre\_\* directory. - -1. Start a command prompt with administrator privilege and run the processor-specific WDK tool Devcon.exe to launch the installation. For example: +Installation instructions +------------------------- +1. Build the solution and locate the produced processor-appropriate avssamp.inf and avssamp.sys files + - For your convenience, you may wish to move these files into a separate folder such as C:\AVStream +2. Start a command prompt with administrator privilege and run the processor-specific WDK tool Devcon.exe to launch the installation. For example: `C:\WinDDK\7600.16384.0\tools\devcon\i386\devcon.exe install C:\AVstream\avssamp.inf SW\{20698827-7099-4c4e-861A-4879D639A35F}` -## Programming tour +Programming Tour +---------------- -[**DriverEntry**](https://docs.microsoft.com/previous-versions//ff558717(v=vs.85)) in Avssamp.cpp is the initial point of entry into the driver. This routine passes control to AVStream by calling [**KsInitializeDriver**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/nf-ks-ksinitializedriver). In this call, the minidriver passes the device descriptor, an AVStream structure that recursively defines the AVStream object hierarchy for a driver. This is common behavior for an AVStream minidriver. +[**DriverEntry**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff558717) in Avssamp.cpp is the initial point of entry into the driver. This routine passes control to AVStream by calling [**KsInitializeDriver**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff562683). In this call, the minidriver passes the device descriptor, an AVStream structure that recursively defines the AVStream object hierarchy for a driver. This is common behavior for an AVStream minidriver. -Filter.cpp is where the sample lays out the [**KSPIN\_DESCRIPTOR\_EX**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/ns-ks-_kspin_descriptor_ex) structure for the single capture pin. Audio.cpp contains the **KSPIN\_DESCRIPTOR\_EX** structure for the audio capture pin. This pin is dynamically created only if C:\\avssamp.wav exists and is a valid and readable PCM format wave file. +Filter.cpp is where the sample lays out the [**KSPIN\_DESCRIPTOR\_EX**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff563534) structure for the single capture pin. Audio.cpp contains the **KSPIN\_DESCRIPTOR\_EX** structure for the audio capture pin. This pin is dynamically created only if C:\\avssamp.wav exists and is a valid and readable PCM format wave file. -The filter dispatch structure [**KSFILTER\_DISPATCH**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/ns-ks-_ksfilter_dispatch) in Filter.cpp provides dispatches to create and process data. The **DispatchProcess** method is defined inline in Filter.h. It calls the **Process** method in Filter.cpp in the context of the **CCaptureFilter** class. Be aware that the process dispatch is provided in **KSFILTER\_DISPATCH** because this sample is filter-centric. +The filter dispatch structure [**KSFILTER\_DISPATCH**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff562554) in Filter.cpp provides dispatches to create and process data. The **DispatchProcess** method is defined inline in Filter.h. It calls the **Process** method in Filter.cpp in the context of the **CCaptureFilter** class. Be aware that the process dispatch is provided in **KSFILTER\_DISPATCH** because this sample is filter-centric. -Audio.cpp lays out a [**KSPIN\_DISPATCH**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/ns-ks-_kspin_dispatch) pin dispatch structure, which contains the dispatch table for the audio pin. Be aware that the **Process** member of this structure is **NULL** because the sample is filter-centric. Similarly, Video.cpp contains the **KSPIN\_DISPATCH** structure for the video capture pin, again with the **Process** member set to **NULL**. +Audio.cpp lays out a [**KSPIN\_DISPATCH**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff563535) pin dispatch structure, which contains the dispatch table for the audio pin. Be aware that the **Process** member of this structure is **NULL** because the sample is filter-centric. Similarly, Video.cpp contains the **KSPIN\_DISPATCH** structure for the video capture pin, again with the **Process** member set to **NULL**. For more information, see the comments in all .cpp files. -## File manifest - -| File | Description | -| --- | --- | -| Audio.cpp | Audio capture pin implementation | -| Audio.h | Header file for Audio.cpp | -| Avssamp.cpp | Main file for the AVStream filter-centric sample. | -| Avssamp.h | Main header for the AVStream filter-centric sample. | -| Avssamp.inf | Installation information for the AVStream sample driver (avssamp.sys). | -| 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. | -| Filter.cpp | Capture filter implementation (including frame synthesis) for the fake capture filter. | -| Filter.h | Filter level header for the filter-centric capture filter. | -| 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. | -| Video.cpp | Video capture pin implementation | -| Video.h | Video capture pin header | -| Wave.cpp | Wave object implementation | -| Wave.h | Wave object header | +File Manifest +------------- + +File | Description +-----|---------- +Audio.cpp | Audio capture pin implementation. +Audio.h | Header file for Audio.cpp. +Avssamp.cpp | Main file for the AVStream filter-centric sample. +Avssamp.h | Main header for the AVStream filter-centric sample. +Avssamp.inx | Installation information template for the AVStream sample driver (avssamp.sys), from which an architecture specific INF file is generated on build. +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. +Filter.cpp | Capture filter implementation (including frame synthesis) for the fake capture filter. +Filter.h | Filter level header for the filter-centric capture filter. +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. +Video.cpp | Video capture pin implementation. +Video.h | Video capture pin header. +Wave.cpp | Wave object implementation +Wave.h | Wave object header diff --git a/avstream/avssamp/audio.cpp b/avstream/avssamp/audio.cpp index 579fa002..cc35f869 100644 --- a/avstream/avssamp/audio.cpp +++ b/avstream/avssamp/audio.cpp @@ -358,7 +358,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 acceptable and perform the actions necessary + Validate that the format is acceptible and perform the actions necessary to change format if appropriate. Arguments: 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 Binary files /dev/null and b/avstream/avssamp/avssamp.inx 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 @@ - + 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/sampledevicemft/basepin.cpp b/avstream/sampledevicemft/basepin.cpp index d4220397..9c989000 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 mediaBuffer; + wil::com_ptr_nothrow 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 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(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(this); + m_asyncCallback = new (std::nothrow) CDMFTAsyncCallback(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 spUnknown; ComPtr 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(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 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 m_spSourceTransform; /*Source Transform i.e. DevProxy*/ @@ -520,15 +520,27 @@ protected: DeviceStreamState m_preferredStreamState; ComPtr 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 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 > 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 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 outPin = GetOutPin(dwOutputStreamID); + RETURN_HR_IF_NULL(E_INVALIDARG, outPin); + RETURN_HR_IF_NULL(E_INVALIDARG, pAllocator); + + wil::com_ptr_nothrow 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 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 pMediaType = nullptr; + ComPtr 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(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 @@ + + + + + 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}. + + + \ 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 @@ Source Files + \ 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 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(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(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 nulltee = wil::make_unique_nothrow(this); + RETURN_IF_NULL_ALLOC(nulltee); + + if (allocatorUsage == MFSampleAllocatorUsage_DoesNotAllocate) + { + m_spTeer.Attach(nulltee.release()); /*A simple passthrough*/ + } + else + { + wistd::unique_ptr 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(nulltee.release(), pinCategory(), pAllocator); + } + else + { + sampleCopytee = wil::make_unique_nothrow(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 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 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 spTransform = Transform(); + ComPtr 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 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(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(this); + m_asyncCallback = new (std::nothrow) CDMFTAsyncCallback(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 spOutputSample; + CAutoLock lock(m_Lock); ComPtr 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 spDecoderTemp; ComPtr 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 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 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 spXvp; + ComPtr 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 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 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(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 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 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 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 &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(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 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 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 m_spDeviceManagerUnk; - ComPtr m_spAllocator; + ComPtr m_spPrivateAllocator; + ComPtr 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 > m_asyncCallback; + ComPtr > m_asyncCallback; HRESULT m_asyncHresult; DWORD m_lNeedInputRequest; GUID m_streamCategory; // Needed for bind flags @@ -381,14 +479,22 @@ protected: ComPtr m_spUnprocessedSample; DWORD m_dwQueueId; DWORD m_dwCameraStreamWorkQueueId; - CCritSec m_critSec; std::deque > 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 spPrivateAllocator; +#if ((defined NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB)) + wil::com_ptr_nothrow spDefaultAllocator; +#endif + wil::com_ptr_nothrow 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/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 +#include +#include +#include + // @@@@ 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 diff --git a/avstream/samplemft0/README.md b/avstream/samplemft0/README.md index 4ed8adbf..42f23db4 100644 --- a/avstream/samplemft0/README.md +++ b/avstream/samplemft0/README.md @@ -1,39 +1,37 @@ ---- -page_type: sample -description: "A driver MFT for use with a camera's Windows device app." -languages: -- cpp -products: -- windows -- windows-wdk ---- + -# Driver MFT Sample +Driver MFT Sample +================= -Provides a *driver MFT* for use with a camera's UWP device app.A *driver MFT* is a Media Foundation Transform that's used with a specific camera when capturing video. The driver MFT is also known as MFT0 because it is the first MFT applied to the video stream captured from the camera. This MFT can provide a video effect or other processing when capturing photos or video from the camera. It can be distributed along with the driver package for a camera. +Provides a *driver MFT* for use with a camera's Windows Store device app.A *driver MFT* is a Media Foundation Transform that's used with a specific camera when capturing video. The driver MFT is also known as MFT0 because it is the first MFT applied to the video stream captured from the camera. This MFT can provide a video effect or other processing when capturing photos or video from the camera. It can be distributed along with the driver package for a camera. -In this sample, the driver MFT, when enabled, replaces a portion of the captured video with a green box. To test this sample, download the [UWP device app for camera sample](https://go.microsoft.com/fwlink/p/?linkid=249442) and the [Camera Capture UI sample](https://go.microsoft.com/fwlink/p/?linkid=249441). - -The **UWP device app for camera sample** provides a *UWP device app* that controls the effect implemented by the driver MFT. - -The **Camera Capture UI sample** provides a way to invoke the **UWP device app**. +In this sample, the driver MFT, when enabled, replaces a portion of the captured video with a green box. To test this sample, download the [Windows Store device app for camera sample](http://go.microsoft.com/fwlink/p/?linkid=249442) and the [Camera Capture UI sample](http://go.microsoft.com/fwlink/p/?linkid=249441). The [Windows Store device app for camera sample](http://go.microsoft.com/fwlink/p/?linkid=249442) provides a *Windows Store device app* that controls the effect implemented by the driver MFT. The [Camera Capture UI sample](http://go.microsoft.com/fwlink/p/?linkid=249441) provides a way to invoke the *Windows Store device app*. This sample is designed to be used with a specific camera. To run the sample, you need the your camera's device ID and device metadata package. -## Related topics -### Concepts +Related topics +-------------- + +**Concepts** -[UWP device apps for cameras](https://docs.microsoft.com/windows-hardware/drivers/devapps/uwp-device-apps-for-webcams) +[Windows Store device apps for cameras](http://go.microsoft.com/fwlink/p/?LinkId=306683) -[Media Foundation Transforms](https://docs.microsoft.com/windows/win32/medfound/media-foundation-transforms) +[Media Foundation Transforms](http://msdn.microsoft.com/en-us/library/windows/hardware/ms703138) -[Streaming media device driver design guide](https://docs.microsoft.com/windows-hardware/drivers/stream) +[Roadmap for Developing Streaming Media Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff568130) -[Universal camera driver design guide for Windows 10](https://docs.microsoft.com/windows-hardware/drivers/stream/windows-10-technical-preview-camera-drivers-design-guide) +[Universal camera driver design guide for Windows 10](https://msdn.microsoft.com/en-us/Library/Windows/Hardware/dn937080) -### Samples +**Samples** -[Device app for camera sample](https://go.microsoft.com/fwlink/p/?linkid=249442) +[Windows Store device app for camera sample](http://go.microsoft.com/fwlink/p/?linkid=249442) -[Camera Capture UI sample](https://go.microsoft.com/fwlink/p/?linkid=249441%20) +[Camera Capture UI sample](http://go.microsoft.com/fwlink/p/?linkid=249441%20) -- cgit v1.3.1 From 2a945024ac070bd5d7bef09cb3cbef67757a2a44 Mon Sep 17 00:00:00 2001 From: Joel Corley Date: Tue, 21 Jan 2020 17:45:06 -0800 Subject: Add missing nuget package file. --- avstream/sampledevicemft/packages.config | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 avstream/sampledevicemft/packages.config 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 @@ + + + + \ No newline at end of file -- cgit v1.3.1 From e787e936941ebdd25c5d4e5758fe52b8e2b8d4e5 Mon Sep 17 00:00:00 2001 From: Joel Corley Date: Tue, 11 Feb 2020 15:56:59 -0800 Subject: Revert the accidential overwriting of README.MD files. --- avstream/avscamera/README.md | 30 ++++++++------ avstream/avshws/README.md | 95 ++++++++++++++++++++++--------------------- avstream/avssamp/README.md | 87 +++++++++++++++++++-------------------- avstream/samplemft0/README.md | 48 +++++++++++----------- 4 files changed, 134 insertions(+), 126 deletions(-) diff --git a/avstream/avscamera/README.md b/avstream/avscamera/README.md index ef956c88..da8e8d65 100644 --- a/avstream/avscamera/README.md +++ b/avstream/avscamera/README.md @@ -1,22 +1,26 @@ - - -AvsCamera: AVStream Camera Sample Driver -======================================== -The AvsCamera sample provides a pin-centric AVStream capture driver for a simulated front and back camera. The driver performs simulated captures at 320x240 or 640x480 in RGB24, RGB32, YUY2 and NV12 formats at various frame rates. The purpose of the sample is to demonstrate how to write a fully functional AVStream camera driver. +--- +page_type: sample +description: "Provides a pin-centric AVStream capture driver for a simulated front and back camera that performs simulated captures." +urlFragment: avscamera +languages: +- cpp +products: +- windows +- windows-wdk +--- + +# AvsCamera - AVStream Camera Sample Driver + +The AvsCamera sample provides a pin-centric AVStream capture driver for a simulated front and back camera. The driver performs simulated captures at 320x240 or 640x480 in RGB24, RGB32, YUY2 and NV12 formats at various frame rates. The purpose of the sample is to demonstrate how to write a fully functional AVStream camera driver. This sample features strong parameter validation and overflow detection. It provides validation and simulation logic for all advanced camera controls in the CCaptureFilter class. A real camera driver would replace the filter automation table and CSensor and CSynthesizer class hierarchies to produce a new camera driver. The sample comes with its own MFT0 called AvsCameraMft0.dll. This MFT0 is used to parse metadata supplied in the AvsCamera driver samples. The metadata communications from the driver is primarily a private channel to its MFT0. The MFT0 is responsible for reformatting that information for the capture pipeline. ## Universal Windows Driver Compliant + This sample builds a Universal Windows Driver. It uses only APIs and DDIs that are included in OneCoreUAP. The sample works on 32-bit and 64-bit x86, amd64 and arm platforms. Once installed, the simulated camera should show in the Windows Inbox camera app. ## Building the sample -The AvsCamera sample can be built by opening the AvsCamera.sln solution file. A successful build produces AvsCamera.sys, AvsCameraMft0.dll, AvsCamera.inf and AvsCamera.cat. + +The AvsCamera sample can be built by opening the AvsCamera.sln solution file. A successful build produces AvsCamera.sys, AvsCameraMft0.dll, AvsCamera.inf and AvsCamera.cat. diff --git a/avstream/avshws/README.md b/avstream/avshws/README.md index 109bc968..9a222462 100644 --- a/avstream/avshws/README.md +++ b/avstream/avshws/README.md @@ -1,88 +1,89 @@ - +--- +page_type: sample +description: "A simulated hardware sample driver providing a pin-centric capture driver to simulate AV capture hardware." +languages: +- cpp +products: +- windows +- windows-wdk +--- -AVStream simulated hardware sample driver (Avshws) -================================================== +# AVStream simulated hardware sample driver (Avshws) -The AVStream simulated hardware sample driver (Avshws) provides a pin-centric [AVStream](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554240) capture driver for a simulated piece of hardware. This streaming media driver performs video captures at 320 x 240 pixels in either RGB24 or YUV422 format using direct memory access (DMA) into capture buffers. The purpose of the sample is to demonstrate how to write a pin-centric AVStream minidriver. The sample also shows how to implement DMA by using the related functionality provided by the AVStream class driver. +The AVStream simulated hardware sample driver (Avshws) provides a pin-centric [AVStream](https://docs.microsoft.com/windows-hardware/drivers/stream/avstream-overview) capture driver for a simulated piece of hardware. This streaming media driver performs video captures at 320 x 240 pixels in either RGB24 or YUV422 format using direct memory access (DMA) into capture buffers. The purpose of the sample is to demonstrate how to write a pin-centric AVStream minidriver. The sample also shows how to implement DMA by using the related functionality provided by the AVStream class driver. This sample features enhanced parameter validation and overflow detection. -Provision a target computer ---------------------------- +## Provision a target computer After you've installed the sample on your host computer, run Visual Studio, and from the **File** menu, select **Open**, then **Project/Solution...**, navigate to the directory where you've copied the Avshws sample, then to the C++ folder, and select **avshws.vcxproj** (the VC++ Project). -In the **Solution Explorer** pane in Visual Studio, at the top is **Solution 'avshws'**. Right-click this and select **Configuration Manager**. Follow the instructions in [Building a Driver with the WDK](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644) to set the platform, operating system, and debug configuration you want to use, and to build the sample. This sample project will automatically sign the driver package. +In the **Solution Explorer** pane in Visual Studio, at the top is **Solution 'avshws'**. Right-click this and select **Configuration Manager**. Follow the instructions in [Building a Driver with Visual Studio and the WDK](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver) to set the platform, operating system, and debug configuration you want to use, and to build the sample. This sample project will automatically sign the driver package. -Provision your target computer using instructions in, for example, [Preparing a Computer for Provisioning](http://msdn.microsoft.com/en-us/library/windows/hardware/dn265573). Ensure that in the **Network and Sharing Center** control panel your target computer has **Network Discovery** and **File and Printer Sharing** enabled. +Provision your target computer using instructions in, for example, [Provision a computer for driver deployment and testing](https://docs.microsoft.com/windows-hardware/drivers/gettingstarted/provision-a-target-computer-wdk-8-1). Ensure that in the **Network and Sharing Center** control panel your target computer has **Network Discovery** and **File and Printer Sharing** enabled. -Deploy the driver to the target computer ----------------------------------------- +## Deploy the driver to the target computer -Now you can deploy the Avshws driver that you've just built to the target computer, using guidance in [Deploying a Driver to a Test Computer](http://msdn.microsoft.com/en-us/library/windows/hardware/hh454834). Specifically, find the package file under the **Package** folder in the Avshws solution. Right-click **package** and select **Properties**. Under Configuration Properties, click **Driver install** and then **Deployment**. Here you must click the check box for **Enable deployment**, and then click the button to the right of **\**. In the next dialog you enter the **Target Computer Name** and can let the host computer automatically provision the target computer and set up debugger options. +Now you can deploy the Avshws driver that you've just built to the target computer, using guidance in [Deploying a Driver to a Test Computer](https://docs.microsoft.com/windows-hardware/drivers/develop/deploying-a-driver-to-a-test-computer). Specifically, find the package file under the **Package** folder in the Avshws solution. Right-click **package** and select **Properties**. Under Configuration Properties, click **Driver install** and then **Deployment**. Here you must click the check box for **Enable deployment**, and then click the button to the right of **\**. In the next dialog you enter the **Target Computer Name** and can let the host computer automatically provision the target computer and set up debugger options. Finally, in Visual Studio, from the **Build** menu select **Deploy Solution** to deploy the sample to the target computer. On the target computer, you can see the deployed package in the **%Systemdrive%\\drivertest\\drivers** folder. -Install the driver ------------------- +## Install the driver On the target computer, open Device Manager, and follow these steps: -1. In the **Action** menu, click **Add Legacy Hardware**, and the **Add Hardware Wizard** appears. Click **Next** and then **Next** again. -2. In the **Add Hardware** window, select **Show All Devices**. -3. In the **Manufacturer** list in the left pane, click **Microsoft**. -4. You should see the **AVStream Simulated Hardware Sample** in the **Model** pane on the right. Click this and then click **Next**. -5. Click **Next** again to install the driver, and then click **Finish** to exit the wizard. +1. In the **Action** menu, click **Add Legacy Hardware**, and the **Add Hardware Wizard** appears. Click **Next** and then **Next** again. + +1. In the **Add Hardware** window, select **Show All Devices**. + +1. In the **Manufacturer** list in the left pane, click **Microsoft**. + +1. You should see the **AVStream Simulated Hardware Sample** in the **Model** pane on the right. Click this and then click **Next**. + +1. Click **Next** again to install the driver, and then click **Finish** to exit the wizard. The sample driver now appears in the Device Manager console tree under **Sound, video and game controllers**. The Avshws INF file will be on the system drive at, for example, **...windows\\System32\\DriverStore\\FileRepository\\**. -Sample code hierarchy ---------------------- +## Sample code hierarchy -[**DriverEntry**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff558717) in Device.cpp is the initial point of entry into the driver. This routine passes control to AVStream by calling the [**KsInitializeDriver**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff562683) function. In this call, the minidriver passes the device descriptor, an AVStream structure that recursively defines the AVStream object hierarchy for a driver. This is common behavior for an AVStream minidriver. +[**DriverEntry**](https://docs.microsoft.com/previous-versions//ff558717(v=vs.85)) in Device.cpp is the initial point of entry into the driver. This routine passes control to AVStream by calling the [**KsInitializeDriver**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/nf-ks-ksinitializedriver) function. In this call, the minidriver passes the device descriptor, an AVStream structure that recursively defines the AVStream object hierarchy for a driver. This is common behavior for an AVStream minidriver. -At device start time, a simulated piece of capture hardware is created (the **CHardwareSimulation** class), and a DMA adapter is acquired from the operating system and is registered with AVStream by calling the [**KsDeviceRegisterAdapterObject**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff561687) function. This call is required for a sample that performs DMA access directly into the capture buffers, instead of using DMA access to write to a common buffer. The driver creates the [KS Filter](http://msdn.microsoft.com/en-us/library/windows/hardware/ff567644) for this device dynamically by calling the [**KsCreateFilterFactory**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff561650) function. +At device start time, a simulated piece of capture hardware is created (the **CHardwareSimulation** class), and a DMA adapter is acquired from the operating system and is registered with AVStream by calling the [**KsDeviceRegisterAdapterObject**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/nf-ks-ksdeviceregisteradapterobject) function. This call is required for a sample that performs DMA access directly into the capture buffers, instead of using DMA access to write to a common buffer. The driver creates the [KS Filter](https://docs.microsoft.com/windows-hardware/drivers/stream/ks-filters) for this device dynamically by calling the [**KsCreateFilterFactory**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/nf-ks-kscreatefilterfactory) function. -Filter.cpp is where the sample lays out the [**KSPIN\_DESCRIPTOR\_EX**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff563534) structure for the single video pin. In addition, a [**KSFILTER\_DISPATCH**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff562554) structure and a [**KSFILTER\_DESCRIPTOR**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff562553) structure are provided in this source file. The filter dispatch provides only a create dispatch, a routine that is included in Filter.cpp. The process dispatch is provided on the pin because this is a pin-centric sample. +Filter.cpp is where the sample lays out the [**KSPIN\_DESCRIPTOR\_EX**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/ns-ks-_kspin_descriptor_ex) structure for the single video pin. In addition, a [**KSFILTER\_DISPATCH**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/ns-ks-_ksfilter_dispatch) structure and a [**KSFILTER\_DESCRIPTOR**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/ns-ks-_ksfilter_descriptor) structure are provided in this source file. The filter dispatch provides only a create dispatch, a routine that is included in Filter.cpp. The process dispatch is provided on the pin because this is a pin-centric sample. -Capture.cpp contains source for the video capture pin on the capture filter. This is where the [**KSPIN\_DISPATCH**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff563535) structure for the unique pin is provided. This dispatch structure specifies a *Process* callback routine, also defined in this source file. This routine is where stream pointer manipulation and cloning occurs. +Capture.cpp contains source for the video capture pin on the capture filter. This is where the [**KSPIN\_DISPATCH**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/ns-ks-_kspin_dispatch) structure for the unique pin is provided. This dispatch structure specifies a *Process* callback routine, also defined in this source file. This routine is where stream pointer manipulation and cloning occurs. The process callback is one of two routines of interest in Capture.cpp that demonstrate how to perform DMA transfers with AVStream functionality. The other is the **CCapturePin::CompleteMappings** method. These two methods show how to use the queue, obtain clone pointers, use scatter/gather lists, and perform other DMA-related tasks. For more information, see the comments in all .cpp files. -Run the sample --------------- +## Run the sample Follow these steps to see how the sample driver functions: -1. After installation has completed, access the driver through the Graphedt tool. Graphedt.exe is available in the *tools* directory of the WDK. -2. Before running GraphEdit, use the regsvr32 utility to register the proppage.dll DLL and to enable GraphEdit to display property pages for some of the built-in Microsoft DirectShow filters. Open an elevated command window with Administrator privileges, and navigate to the WDK or SDK *tools* directory that contains proppage.dll. -3. On the command line, type regsvr32 proppage.dll. If the registration succeeds, you'll get a message, "DllRegisterServer in proppage.dll succeeded." Click OK. -4. In the Graphedt tool, click the **Graph** menu and click **Insert Filters**. The sample appears under "WDM Streaming Capture Devices" as "avshws Source." -5. Click **Insert Filter**. The sample appears in the graph as a single filter labeled, "avshws Source." There is one output pin, which is the video capture pin. This pin emits video in YUY2 format. -6. Attach this filter to either a DirectShow Video Renderer or to the VMR default video renderer. Then click **Play**. +1. After installation has completed, access the driver through the Graphedt tool. Graphedt.exe is available in the *tools* directory of the WDK. + +1. Before running GraphEdit, use the regsvr32 utility to register the proppage.dll DLL and to enable GraphEdit to display property pages for some of the built-in Microsoft DirectShow filters. Open an elevated command window with Administrator privileges, and navigate to the WDK or SDK *tools* directory that contains proppage.dll. + +1. On the command line, type regsvr32 proppage.dll. If the registration succeeds, you'll get a message, "DllRegisterServer in proppage.dll succeeded." Click OK. + +1. In the Graphedt tool, click the **Graph** menu and click **Insert Filters**. The sample appears under "WDM Streaming Capture Devices" as "avshws Source." + +1. Click **Insert Filter**. The sample appears in the graph as a single filter labeled, "avshws Source." There is one output pin, which is the video capture pin. This pin emits video in YUY2 format. + +1. Attach this filter to either a DirectShow Video Renderer or to the VMR default video renderer. Then click **Play**. The output that is produced by the sample is a 320 x 240 pixel image of standard EIA-189-A color bars. In the middle of the image near the bottom, a clock appears over the image. This clock displays the elapsed time since the graph was introduced into the run state following the last stop. The clock display format is MINUTES:SECONDS.HUNDREDTHS. In the upper-left corner of the image, a counter counts the number of frames that have been dropped since the graph was introduced into the run state after the last stop. -Code tour ---------- - -### File Manifest +## File manifest -File | Description ------|------------ -Avshws.h | Main header file for the sample. -Avshws.inx | Template installation file from which an architecture specific INF file is generated on build. +| File | Description | +| --- | --- | +| 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. diff --git a/avstream/avssamp/README.md b/avstream/avssamp/README.md index 44a44139..42f0d393 100644 --- a/avstream/avssamp/README.md +++ b/avstream/avssamp/README.md @@ -1,57 +1,58 @@ - +--- +page_type: sample +description: "An AVStream filter-centric simulated capture sample driver with functional audio." +languages: +- cpp +products: +- windows +- windows-wdk +--- -AVStream filter-centric simulated capture sample driver (Avssamp) -================================================================= +# AVStream filter-centric simulated capture sample driver (Avssamp) -The AVStream filter-centric simulated capture sample driver (Avssamp) provides a filter-centric [AVStream](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554240) capture driver with functional audio. This streaming media driver performs video captures at 320 x 240 pixel resolution in RGB24 or YUV422 format while playing a user-provided Pulse Code Modulation (PCM) wave audio file in a loop. The sample demonstrates how to write a filter-centric AVStream minidriver. +The AVStream filter-centric simulated capture sample driver (Avssamp) provides a filter-centric [AVStream](https://docs.microsoft.com/windows-hardware/drivers/stream/avstream-overview) capture driver with functional audio. This streaming media driver performs video captures at 320 x 240 pixel resolution in RGB24 or YUV422 format while playing a user-provided Pulse Code Modulation (PCM) wave audio file in a loop. The sample demonstrates how to write a filter-centric AVStream minidriver. +## Installation instructions -Installation instructions -------------------------- +1. Copy AVssamp.inf to a directory, for example, C:\\Avstream\\. + +1. In this directory, create a new subdirectory named objfre\_x86 if the target operating system is x86-based, or objfre\_amd64 for an x64-based target operating system, for example, C:\\AVstream\\objfre\_x86\\. + +1. Copy the processor-appropriate Avssamp.sys file to the objfre\_\* directory. + +1. Start a command prompt with administrator privilege and run the processor-specific WDK tool Devcon.exe to launch the installation. For example: -1. Build the solution and locate the produced processor-appropriate avssamp.inf and avssamp.sys files - - For your convenience, you may wish to move these files into a separate folder such as C:\AVStream -2. Start a command prompt with administrator privilege and run the processor-specific WDK tool Devcon.exe to launch the installation. For example: `C:\WinDDK\7600.16384.0\tools\devcon\i386\devcon.exe install C:\AVstream\avssamp.inf SW\{20698827-7099-4c4e-861A-4879D639A35F}` -Programming Tour ----------------- +## Programming tour -[**DriverEntry**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff558717) in Avssamp.cpp is the initial point of entry into the driver. This routine passes control to AVStream by calling [**KsInitializeDriver**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff562683). In this call, the minidriver passes the device descriptor, an AVStream structure that recursively defines the AVStream object hierarchy for a driver. This is common behavior for an AVStream minidriver. +[**DriverEntry**](https://docs.microsoft.com/previous-versions//ff558717(v=vs.85)) in Avssamp.cpp is the initial point of entry into the driver. This routine passes control to AVStream by calling [**KsInitializeDriver**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/nf-ks-ksinitializedriver). In this call, the minidriver passes the device descriptor, an AVStream structure that recursively defines the AVStream object hierarchy for a driver. This is common behavior for an AVStream minidriver. -Filter.cpp is where the sample lays out the [**KSPIN\_DESCRIPTOR\_EX**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff563534) structure for the single capture pin. Audio.cpp contains the **KSPIN\_DESCRIPTOR\_EX** structure for the audio capture pin. This pin is dynamically created only if C:\\avssamp.wav exists and is a valid and readable PCM format wave file. +Filter.cpp is where the sample lays out the [**KSPIN\_DESCRIPTOR\_EX**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/ns-ks-_kspin_descriptor_ex) structure for the single capture pin. Audio.cpp contains the **KSPIN\_DESCRIPTOR\_EX** structure for the audio capture pin. This pin is dynamically created only if C:\\avssamp.wav exists and is a valid and readable PCM format wave file. -The filter dispatch structure [**KSFILTER\_DISPATCH**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff562554) in Filter.cpp provides dispatches to create and process data. The **DispatchProcess** method is defined inline in Filter.h. It calls the **Process** method in Filter.cpp in the context of the **CCaptureFilter** class. Be aware that the process dispatch is provided in **KSFILTER\_DISPATCH** because this sample is filter-centric. +The filter dispatch structure [**KSFILTER\_DISPATCH**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/ns-ks-_ksfilter_dispatch) in Filter.cpp provides dispatches to create and process data. The **DispatchProcess** method is defined inline in Filter.h. It calls the **Process** method in Filter.cpp in the context of the **CCaptureFilter** class. Be aware that the process dispatch is provided in **KSFILTER\_DISPATCH** because this sample is filter-centric. -Audio.cpp lays out a [**KSPIN\_DISPATCH**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff563535) pin dispatch structure, which contains the dispatch table for the audio pin. Be aware that the **Process** member of this structure is **NULL** because the sample is filter-centric. Similarly, Video.cpp contains the **KSPIN\_DISPATCH** structure for the video capture pin, again with the **Process** member set to **NULL**. +Audio.cpp lays out a [**KSPIN\_DISPATCH**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ks/ns-ks-_kspin_dispatch) pin dispatch structure, which contains the dispatch table for the audio pin. Be aware that the **Process** member of this structure is **NULL** because the sample is filter-centric. Similarly, Video.cpp contains the **KSPIN\_DISPATCH** structure for the video capture pin, again with the **Process** member set to **NULL**. For more information, see the comments in all .cpp files. -File Manifest -------------- - -File | Description ------|---------- -Audio.cpp | Audio capture pin implementation. -Audio.h | Header file for Audio.cpp. -Avssamp.cpp | Main file for the AVStream filter-centric sample. -Avssamp.h | Main header for the AVStream filter-centric sample. -Avssamp.inx | Installation information template for the AVStream sample driver (avssamp.sys), from which an architecture specific INF file is generated on build. -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. -Filter.cpp | Capture filter implementation (including frame synthesis) for the fake capture filter. -Filter.h | Filter level header for the filter-centric capture filter. -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. -Video.cpp | Video capture pin implementation. -Video.h | Video capture pin header. -Wave.cpp | Wave object implementation -Wave.h | Wave object header +## File manifest + +| File | Description | +| --- | --- | +| Audio.cpp | Audio capture pin implementation | +| Audio.h | Header file for Audio.cpp | +| Avssamp.cpp | Main file for the AVStream filter-centric sample. | +| Avssamp.h | Main header for the AVStream filter-centric sample. | +| Avssamp.inf | Installation information for the AVStream sample driver (avssamp.sys). | +| 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. | +| Filter.cpp | Capture filter implementation (including frame synthesis) for the fake capture filter. | +| Filter.h | Filter level header for the filter-centric capture filter. | +| 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. | +| Video.cpp | Video capture pin implementation | +| Video.h | Video capture pin header | +| Wave.cpp | Wave object implementation | +| Wave.h | Wave object header | diff --git a/avstream/samplemft0/README.md b/avstream/samplemft0/README.md index 42f23db4..4ed8adbf 100644 --- a/avstream/samplemft0/README.md +++ b/avstream/samplemft0/README.md @@ -1,37 +1,39 @@ - +--- +page_type: sample +description: "A driver MFT for use with a camera's Windows device app." +languages: +- cpp +products: +- windows +- windows-wdk +--- -Driver MFT Sample -================= +# Driver MFT Sample -Provides a *driver MFT* for use with a camera's Windows Store device app.A *driver MFT* is a Media Foundation Transform that's used with a specific camera when capturing video. The driver MFT is also known as MFT0 because it is the first MFT applied to the video stream captured from the camera. This MFT can provide a video effect or other processing when capturing photos or video from the camera. It can be distributed along with the driver package for a camera. +Provides a *driver MFT* for use with a camera's UWP device app.A *driver MFT* is a Media Foundation Transform that's used with a specific camera when capturing video. The driver MFT is also known as MFT0 because it is the first MFT applied to the video stream captured from the camera. This MFT can provide a video effect or other processing when capturing photos or video from the camera. It can be distributed along with the driver package for a camera. -In this sample, the driver MFT, when enabled, replaces a portion of the captured video with a green box. To test this sample, download the [Windows Store device app for camera sample](http://go.microsoft.com/fwlink/p/?linkid=249442) and the [Camera Capture UI sample](http://go.microsoft.com/fwlink/p/?linkid=249441). The [Windows Store device app for camera sample](http://go.microsoft.com/fwlink/p/?linkid=249442) provides a *Windows Store device app* that controls the effect implemented by the driver MFT. The [Camera Capture UI sample](http://go.microsoft.com/fwlink/p/?linkid=249441) provides a way to invoke the *Windows Store device app*. +In this sample, the driver MFT, when enabled, replaces a portion of the captured video with a green box. To test this sample, download the [UWP device app for camera sample](https://go.microsoft.com/fwlink/p/?linkid=249442) and the [Camera Capture UI sample](https://go.microsoft.com/fwlink/p/?linkid=249441). -This sample is designed to be used with a specific camera. To run the sample, you need the your camera's device ID and device metadata package. +The **UWP device app for camera sample** provides a *UWP device app* that controls the effect implemented by the driver MFT. + +The **Camera Capture UI sample** provides a way to invoke the **UWP device app**. +This sample is designed to be used with a specific camera. To run the sample, you need the your camera's device ID and device metadata package. -Related topics --------------- +## Related topics -**Concepts** +### Concepts -[Windows Store device apps for cameras](http://go.microsoft.com/fwlink/p/?LinkId=306683) +[UWP device apps for cameras](https://docs.microsoft.com/windows-hardware/drivers/devapps/uwp-device-apps-for-webcams) -[Media Foundation Transforms](http://msdn.microsoft.com/en-us/library/windows/hardware/ms703138) +[Media Foundation Transforms](https://docs.microsoft.com/windows/win32/medfound/media-foundation-transforms) -[Roadmap for Developing Streaming Media Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff568130) +[Streaming media device driver design guide](https://docs.microsoft.com/windows-hardware/drivers/stream) -[Universal camera driver design guide for Windows 10](https://msdn.microsoft.com/en-us/Library/Windows/Hardware/dn937080) +[Universal camera driver design guide for Windows 10](https://docs.microsoft.com/windows-hardware/drivers/stream/windows-10-technical-preview-camera-drivers-design-guide) -**Samples** +### Samples -[Windows Store device app for camera sample](http://go.microsoft.com/fwlink/p/?linkid=249442) +[Device app for camera sample](https://go.microsoft.com/fwlink/p/?linkid=249442) -[Camera Capture UI sample](http://go.microsoft.com/fwlink/p/?linkid=249441%20) +[Camera Capture UI sample](https://go.microsoft.com/fwlink/p/?linkid=249441%20) -- cgit v1.3.1 From 43e90d07b44b756ce084a31ac3ca154857bb64d8 Mon Sep 17 00:00:00 2001 From: Joel Corley Date: Fri, 3 Apr 2020 14:39:08 -0700 Subject: Undo unnecessary changes to project file. --- avstream/avscamera/mft0/AvsCameraMft0.vcxproj | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/avstream/avscamera/mft0/AvsCameraMft0.vcxproj b/avstream/avscamera/mft0/AvsCameraMft0.vcxproj index 1c59ed8f..518a324f 100644 --- a/avstream/avscamera/mft0/AvsCameraMft0.vcxproj +++ b/avstream/avscamera/mft0/AvsCameraMft0.vcxproj @@ -31,7 +31,7 @@ Windows10 False - Desktop + Universal WindowsApplicationForDrivers10.0 DynamicLibrary @@ -39,7 +39,7 @@ Windows10 True - Desktop + Universal WindowsApplicationForDrivers10.0 DynamicLibrary @@ -47,7 +47,7 @@ Windows10 False - Desktop + Universal WindowsApplicationForDrivers10.0 DynamicLibrary @@ -55,7 +55,7 @@ Windows10 True - Desktop + Universal WindowsApplicationForDrivers10.0 DynamicLibrary @@ -201,7 +201,7 @@ - + @@ -213,4 +213,4 @@ - + \ No newline at end of file -- cgit v1.3.1 From 60dab78e2549a164e5558b2169a900f24ac41434 Mon Sep 17 00:00:00 2001 From: Yiwen Jiang Date: Mon, 6 Apr 2020 11:05:29 -0700 Subject: Replaced ExAllocatePoolWithTag with ExAllocatePoolZero in avsstream samples --- avstream/avscamera/sys/AvsCamera.cpp | 25 +++---------------------- avstream/avscamera/sys/Capture.cpp | 6 +++--- avstream/avshws/capture.cpp | 2 +- avstream/avshws/device.cpp | 25 +++---------------------- avstream/avshws/hwsim.cpp | 2 +- avstream/avssamp/Filter.cpp | 6 +++--- avstream/avssamp/avssamp.cpp | 16 ++-------------- avstream/avssamp/video.cpp | 4 ++-- avstream/avssamp/wave.cpp | 2 +- 9 files changed, 19 insertions(+), 69 deletions(-) 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/Capture.cpp b/avstream/avscamera/sys/Capture.cpp index aadaca4e..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 ( - 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 ( - ExAllocatePoolWithTag ( + ExAllocatePoolZero ( NonPagedPoolNx, max(sizeof(KS_VIDEOINFOHEADER), KS_SIZE_VIDEOHEADER (ConnectionHeader)), AVSHWS_POOLTAG @@ -339,7 +339,7 @@ Return Value: VideoInfoHeader2); m_VideoInfoHeader = reinterpret_cast ( - ExAllocatePoolWithTag( + ExAllocatePoolZero( NonPagedPoolNx, max(sizeof(KS_VIDEOINFOHEADER), ConnectionHeader->bmiHeader.biSize + KS_SIZE_PREHEADER), AVSHWS_POOLTAG 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 ( - 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 ( - ExAllocatePoolWithTag ( + ExAllocatePoolZero ( NonPagedPoolNx, m_ImageSize, AVSHWS_POOLTAG 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 ( - ExAllocatePoolWithTag (PagedPool, sizeof (KSDATARANGE_AUDIO), AVSSMP_POOLTAG) + ExAllocatePoolZero (PagedPool, sizeof (KSDATARANGE_AUDIO), AVSSMP_POOLTAG) ); PKSDATARANGE_AUDIO *DataRanges = reinterpret_cast ( - ExAllocatePoolWithTag (PagedPool, sizeof (PKSDATARANGE_AUDIO), AVSSMP_POOLTAG) + ExAllocatePoolZero (PagedPool, sizeof (PKSDATARANGE_AUDIO), AVSSMP_POOLTAG) ); PKSALLOCATOR_FRAMING_EX Framing = reinterpret_cast ( - 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/video.cpp b/avstream/avssamp/video.cpp index d2291a24..a2acf0ff 100644 --- a/avstream/avssamp/video.cpp +++ b/avstream/avssamp/video.cpp @@ -210,7 +210,7 @@ Return Value: VideoInfoHeader); m_VideoInfoHeader = reinterpret_cast ( - ExAllocatePoolWithTag ( + ExAllocatePoolZero ( NonPagedPool, KS_SIZE_VIDEOHEADER (ConnectionHeader), AVSSMP_POOLTAG @@ -864,7 +864,7 @@ Return Value: if (FromState == KSSTATE_STOP) { m_SynthesisBuffer = reinterpret_cast ( - 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 ( - ExAllocatePoolWithTag (NonPagedPool, DataBlockSize, AVSSMP_POOLTAG) + ExAllocatePoolZero (NonPagedPool, DataBlockSize, AVSSMP_POOLTAG) ); if (!m_WaveData) { -- cgit v1.3.1 From 6568238719a3fe6d317e1d4a13131f5d2ca0234b Mon Sep 17 00:00:00 2001 From: Joel Corley Date: Tue, 7 Apr 2020 00:42:28 -0700 Subject: Fix typos, etc. to address review comments. --- avstream/avscamera/sys/Common.h | 1 - avstream/avscamera/sys/Device.cpp | 4 +--- avstream/avscamera/sys/Sensor.cpp | 2 +- avstream/avscamera/sys/Sensor.h | 1 - avstream/avscamera/sys/filter.h | 2 +- avstream/avssamp/audio.cpp | 2 +- avstream/avssamp/video.cpp | 6 +++--- avstream/sampledevicemft/basepin.cpp | 2 +- 8 files changed, 8 insertions(+), 12 deletions(-) diff --git a/avstream/avscamera/sys/Common.h b/avstream/avscamera/sys/Common.h index d29a0438..7cde102f 100644 --- a/avstream/avscamera/sys/Common.h +++ b/avstream/avscamera/sys/Common.h @@ -33,7 +33,6 @@ #include #include -//#include #include #include #include diff --git a/avstream/avscamera/sys/Device.cpp b/avstream/avscamera/sys/Device.cpp index 9fab69d9..2741da08 100644 --- a/avstream/avscamera/sys/Device.cpp +++ b/avstream/avscamera/sys/Device.cpp @@ -637,9 +637,7 @@ Return Value: (PVOID)&pld) ); - //Also set Panel ID manually, because PnP does not do this for the interface currently - // TODO: This is a bug in PnP that they will fix, so don't check the return code - // It will be read only when fixed. + // Also set Panel ID manually, because PnP does not do this for the interface currently IoSetDeviceInterfacePropertyData(SymbolicLinkName, &DEVPKEY_Device_PanelId, LOCALE_NEUTRAL, diff --git a/avstream/avscamera/sys/Sensor.cpp b/avstream/avscamera/sys/Sensor.cpp index 1f062497..654ea666 100644 --- a/avstream/avscamera/sys/Sensor.cpp +++ b/avstream/avscamera/sys/Sensor.cpp @@ -413,7 +413,7 @@ Return Value: NTSTATUS Status = STATUS_SUCCESS; LONG lPindex = Pin->Id; - // Hold off all image generation while we muck with the capture pin and synthensizer arrays. + // Hold off all image generation while we manipulate the capture pin and synthensizer arrays. KScopedMutex Lock(m_SensorMutex); // diff --git a/avstream/avscamera/sys/Sensor.h b/avstream/avscamera/sys/Sensor.h index c68f1b3a..31b0f3a2 100644 --- a/avstream/avscamera/sys/Sensor.h +++ b/avstream/avscamera/sys/Sensor.h @@ -522,7 +522,6 @@ public: CSynthesizer::Attribute Attrib; LONGLONG Info; LONG PinId; - }; void diff --git a/avstream/avscamera/sys/filter.h b/avstream/avscamera/sys/filter.h index 07f1c0d4..5b272a9d 100644 --- a/avstream/avscamera/sys/filter.h +++ b/avstream/avscamera/sys/filter.h @@ -58,7 +58,7 @@ private: // The AVStream filter object associated with this CCaptureFilter. // CCapturePin **m_pinArray; - ULONG* m_pMinimumRequestedFrames; + ULONG *m_pMinimumRequestedFrames; protected: // diff --git a/avstream/avssamp/audio.cpp b/avstream/avssamp/audio.cpp index cc35f869..579fa002 100644 --- a/avstream/avssamp/audio.cpp +++ b/avstream/avssamp/audio.cpp @@ -358,7 +358,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: diff --git a/avstream/avssamp/video.cpp b/avstream/avssamp/video.cpp index d2291a24..d18dc95d 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 @@ -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: diff --git a/avstream/sampledevicemft/basepin.cpp b/avstream/sampledevicemft/basepin.cpp index 9c989000..563ff610 100644 --- a/avstream/sampledevicemft/basepin.cpp +++ b/avstream/sampledevicemft/basepin.cpp @@ -742,7 +742,7 @@ done: STDMETHODIMP CAsyncInPin::Init() { - m_asyncCallback = new (std::nothrow) CDMFTAsyncCallback(this,m_dwWorkQueueId); + m_asyncCallback = new (std::nothrow) CDMFTAsyncCallback(this, m_dwWorkQueueId); if (!m_asyncCallback) throw bad_alloc(); return S_OK; -- cgit v1.3.1