summaryrefslogtreecommitdiff
path: root/AVStream/avscamera/sys/SensorSimulation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'AVStream/avscamera/sys/SensorSimulation.cpp')
-rw-r--r--AVStream/avscamera/sys/SensorSimulation.cpp3537
1 files changed, 3537 insertions, 0 deletions
diff --git a/AVStream/avscamera/sys/SensorSimulation.cpp b/AVStream/avscamera/sys/SensorSimulation.cpp
new file mode 100644
index 00000000..3ebeb56b
--- /dev/null
+++ b/AVStream/avscamera/sys/SensorSimulation.cpp
@@ -0,0 +1,3537 @@
+/**************************************************************************
+
+ A/V Stream Camera Sample
+
+ Copyright (c) 2014, Microsoft Corporation.
+
+ File:
+
+ SensorSimulation.cpp
+
+ Abstract:
+
+ Simulation class implementation. Derived from the base CSensor object.
+
+ This class simulates a theoretical model camera. The camera supports
+ every modern camera control available and produces a simulation of its
+ behavior. In most cases this simulation is very very basic because we
+ have no actual hardware to work with and there producing a visible
+ effect in the simulation would be difficult or expensive to do.
+
+ History:
+
+ created 5/8/2014
+
+**************************************************************************/
+
+#include "Common.h"
+
+/**************************************************************************
+
+ PAGEABLE CODE
+
+**************************************************************************/
+
+#ifdef ALLOC_PRAGMA
+#pragma code_seg("PAGE")
+#endif // ALLOC_PRAGMA
+
+//
+// The following macro is used to define a legacy control's range and
+// default value. We use the macro simply to minimize the verbosity of
+// our declarations.
+//
+#define DEFINE_LEGACY_CTRL_CAPS( Control, Minimum, Maximum, SteppingDelta, DefValue ) \
+/*-------------------------------------------------------------- \
+ This structure defines what the control is capable of. \
+--------------------------------------------------------------*/ \
+KSPROPERTY_STEPPING_LONG Control##RangeAndStep[] = \
+{ \
+ { \
+ SteppingDelta, /* SteppingDelta */ \
+ 0, /* Reserved */ \
+ Minimum, /* Minimum */ \
+ Maximum /* Maximum */ \
+ } \
+}; \
+ \
+/* This is the default control value. */ \
+const LONG Control##Default = DefValue; \
+ \
+KSPROPERTY_MEMBERSLIST Control##MembersList[] = \
+{ \
+ { \
+ { \
+ KSPROPERTY_MEMBER_STEPPEDRANGES, \
+ sizeof (Control##RangeAndStep), \
+ SIZEOF_ARRAY(Control##RangeAndStep), \
+ 0 \
+ }, \
+ (PVOID)Control##RangeAndStep, \
+ }, \
+ { \
+ { \
+ KSPROPERTY_MEMBER_VALUES, \
+ sizeof (Control##Default), \
+ 1, \
+ KSPROPERTY_MEMBER_FLAG_DEFAULT \
+ }, \
+ (PVOID)&Control##Default \
+ } \
+}; \
+ \
+KSPROPERTY_VALUES Control##Values = \
+{ \
+ { \
+ STATICGUIDOF(KSPROPTYPESETID_General), \
+ VT_I4, \
+ 0 \
+ }, \
+ SIZEOF_ARRAY(Control##MembersList), \
+ Control##MembersList \
+};
+
+DEFINE_LEGACY_CTRL_CAPS( ZoomRelative, -2, +2, 1, 0 )
+DEFINE_LEGACY_CTRL_CAPS( Zoom, FOCALLENGTH_OPTICAL_MIN, FOCALLENGTH_OPTICAL_MAX, 1, FOCALLENGTH_OCULAR )
+DEFINE_LEGACY_CTRL_CAPS( Pan, -180, 180, 1, 0 )
+DEFINE_LEGACY_CTRL_CAPS( Roll, -180, 180, 1, 0 )
+DEFINE_LEGACY_CTRL_CAPS( Tilt, -180, 180, 1, 0 )
+DEFINE_LEGACY_CTRL_CAPS( BacklightCompensation, 0, 1, 1, 0 )
+DEFINE_LEGACY_CTRL_CAPS( Brightness, -10000, 10000, 1, 750 )
+DEFINE_LEGACY_CTRL_CAPS( Contrast, -10000, 10000, 1, 100 )
+DEFINE_LEGACY_CTRL_CAPS( Hue, -18000, 18000, 1, 0 )
+DEFINE_LEGACY_CTRL_CAPS( PLF, POWERLINEFREQ_DISABLED, POWERLINEFREQ_AUTO, 1, POWERLINEFREQ_DEFAULT )
+DEFINE_LEGACY_CTRL_CAPS( WhiteBalance, WHITEBALANCE_MIN, WHITEBALANCE_MAX, WHITEBALANCE_STEP, WHITEBALANCE_DEF )
+DEFINE_LEGACY_CTRL_CAPS( Exposure, EXPOSURE_BILOG_MIN, EXPOSURE_BILOG_MAX, EXPOSURE_BILOG_STEP, EXPOSURE_BILOG_DEF)
+DEFINE_LEGACY_CTRL_CAPS( Focus, 1, 1200, 1, 100 );
+
+void
+CSensorSimulation::
+FocusConvergence(
+ _In_opt_ PVOID Context
+)
+/*++
+
+Routine Description:
+
+ A timer callback that simulates focus convergence.
+
+ Update the focus state to focused.
+
+ Update the position to a random location that is in bounds if we are in
+ an auto or continuous auto mode. The new location is probably not
+ realistic; but it is important to simulate the change in location for
+ testing.
+
+ Notice that we do no kick off the timer again on continuous auto focus.
+ A camera that is performing continuous auto focus in software would
+ probably do something there.
+
+Arguments:
+
+ Context -
+ In our case, this is a pointer to our simulation object.
+
+Return Value:
+
+ None
+
+--*/
+{
+ PAGED_CODE();
+
+ if( Context )
+ {
+ CSensorSimulation *Sensor = (CSensorSimulation *) Context;
+ KScopedMutex lock( Sensor->m_SensorMutex );
+
+ if( Sensor->m_FocusNotifier )
+ {
+ Sensor->m_FocusNotifier->Set();
+ Sensor->m_FocusNotifier = nullptr;
+ }
+
+ // Let's just fake a focus change if we get here from somewhere else.
+ // This only applies to auto focus modes and only if we're not focused.
+ if( (Sensor->m_GlobalIspSettings.FocusMode &
+ (KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO | KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS)) &&
+ Sensor->m_FocusState != KSCAMERA_EXTENDEDPROP_FOCUSSTATE_FOCUSED )
+ {
+ Sensor->m_GlobalIspSettings.FocusSetting.VideoProc.Value.ul =
+ GetRandom( Sensor->m_GlobalIspSettings.FocusSetting.Min,
+ Sensor->m_GlobalIspSettings.FocusSetting.Max );
+ }
+ else if( Sensor->m_GlobalIspSettings.FocusMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL )
+ {
+ switch( Sensor->m_GlobalIspSettings.FocusMode & KSCAMERA_EXTENDEDPROP_FOCUS_DISTANCE_MASK )
+ {
+ case KSCAMERA_EXTENDEDPROP_FOCUS_DISTANCE_INFINITY:
+ Sensor->m_GlobalIspSettings.FocusSetting.VideoProc.Value.ul =
+ Sensor->m_GlobalIspSettings.FocusSetting.Max;
+ break;
+
+ case KSCAMERA_EXTENDEDPROP_FOCUS_DISTANCE_HYPERFOCAL:
+ Sensor->m_GlobalIspSettings.FocusSetting.VideoProc.Value.ul =
+ Sensor->m_GlobalIspSettings.FocusSetting.Max - Sensor->m_GlobalIspSettings.FocusSetting.Step;
+ break;
+
+ case KSCAMERA_EXTENDEDPROP_FOCUS_DISTANCE_NEAREST:
+ Sensor->m_GlobalIspSettings.FocusSetting.VideoProc.Value.ul =
+ Sensor->m_GlobalIspSettings.FocusSetting.Min;
+ break;
+
+ }
+ }
+
+ // TODO:
+ // If we're continuous focus, we should probably kick off another focus change here...
+ // ... but that tends to mess with testing.
+
+ // We always want to transition to here.
+ Sensor->m_FocusState = KSCAMERA_EXTENDEDPROP_FOCUSSTATE_FOCUSED;
+ }
+}
+
+void
+CSensorSimulation::
+FocusRectConvergence(
+ _In_opt_ PVOID Context
+)
+/*++
+
+Routine Description:
+
+ A timer callback that simulates FocusRect convergence.
+
+Arguments:
+
+ Context -
+ In our case, this is a pointer to our simulation object.
+
+Return Value:
+
+ None
+
+--*/
+{
+ PAGED_CODE();
+
+ if( Context )
+ {
+ CSensorSimulation *Sensor = (CSensorSimulation *) Context;
+ KScopedMutex lock( Sensor->m_SensorMutex );
+
+ if( Sensor->m_FocusRectNotifier )
+ {
+ Sensor->m_FocusRectNotifier->Set();
+ Sensor->m_FocusRectNotifier = nullptr;
+ }
+
+ // Not much else to do here.
+ }
+}
+
+CSensorSimulation::CSensorSimulation(
+ _In_ CCaptureDevice *Device,
+ _In_ const KSFILTER_DESCRIPTOR *Descriptors
+)
+ : CSensor( Device, Descriptors->PinDescriptorsCount )
+ , m_Descriptors( Descriptors )
+ , m_MetadataInfo( nullptr )
+ , m_FocusTimer( nullptr )
+ , m_FocusRectTimer( nullptr )
+
+{
+ PAGED_CODE();
+
+ KeQuerySystemTime (&m_StartTime);
+}
+
+
+CSensorSimulation::~CSensorSimulation()
+{
+ PAGED_CODE();
+
+ delete m_FocusTimer;
+ delete m_FocusRectTimer;
+ delete [] m_MetadataInfo;
+ delete [] (PBYTE) m_pPerFrameSettings;
+ delete [] m_WarmStartEnabled;
+}
+
+NTSTATUS
+CSensorSimulation::
+ProgramDefaults()
+/*++
+
+Routine Description:
+
+ Reset our simulation back to the DDI-specified defaults.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ Success / Failure
+
+--*/
+{
+ PAGED_CODE();
+
+ DBG_ENTER("()");
+
+ m_FocusNotifier = nullptr;
+ m_pPerFrameSettings = nullptr;
+
+
+ m_FaceDetectionMax = MAX_FACES;
+ m_FaceDetectionFlags = KSCAMERA_EXTENDEDPROP_FACEDETECTION_OFF;
+ m_FaceDetectionCurrentMax = 0;
+ m_AutoFocusLock = false;
+ m_AutoExposureLock = false;
+ m_AutoWhitebalanceLock = false;
+ m_Flash = 0;
+ m_VideoStabMode = 0;
+ m_VFR = KSCAMERA_EXTENDEDPROP_VFR_ON;
+ m_VideoHDR = KSCAMERA_EXTENDEDPROP_VIDEOHDR_OFF;
+ m_VideoStabilization = KSCAMERA_EXTENDEDPROP_VIDEOSTABILIZATION_OFF;
+ m_Histogram = KSCAMERA_EXTENDEDPROP_HISTOGRAM_OFF;
+ m_OpticalImageStabilization = KSCAMERA_EXTENDEDPROP_OIS_AUTO;
+
+ m_AdvancedPhoto.PinId = GetNextStillIndex();
+ m_AdvancedPhoto.Flags = KSCAMERA_EXTENDEDPROP_ADVANCEDPHOTO_OFF;
+ m_AdvancedPhoto.Capability = KSCAMERA_EXTENDEDPROP_ADVANCEDPHOTO_OFF |
+ KSCAMERA_EXTENDEDPROP_ADVANCEDPHOTO_AUTO |
+ KSCAMERA_EXTENDEDPROP_ADVANCEDPHOTO_HDR |
+ KSCAMERA_EXTENDEDPROP_ADVANCEDPHOTO_FNF |
+ KSCAMERA_EXTENDEDPROP_ADVANCEDPHOTO_ULTRALOWLIGHT;
+
+ m_FocusRect.left = 0;
+ m_FocusRect.top = 0;
+ m_FocusRect.right = 0;
+ m_FocusRect.bottom = 0;
+
+ m_FocusState = KSCAMERA_EXTENDEDPROP_FOCUSSTATE_UNINITIALIZED;
+
+ m_PhotoMode = CExtendedPhotoMode();
+ m_PhotoMode.Capability = KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL | KSCAMERA_EXTENDEDPROP_PHOTOMODE_SEQUENCE;
+ m_PhotoMode.PinId = GetNextStillIndex();
+ m_PhotoMode.MaxHistoryFrames() = IMAGE_CAPTURE_PIN_MAXIMUM_HISTORY_FRAMES;
+ m_PhotoMode.RequestedHistoryFrames() = 0;
+ m_PhotoMode.SubMode() = KSCAMERA_EXTENDEDPROP_PHOTOMODE_SEQUENCE_SUB_NONE;
+
+ m_MaxFrameRate = CExtendedProperty(); // assume nothing.
+
+ for( ULONG Index = GetNextStillIndex(); IsValidIndex( Index ); Index = GetNextStillIndex( Index ) )
+ {
+ SetQPC( Index, 0 );
+ }
+ m_TorchMode.Flags = KSCAMERA_EXTENDEDPROP_VIDEOTORCH_OFF;
+ m_TorchMode = 50UL;
+
+ m_OptimizationHint.Flags = KSCAMERA_EXTENDEDPROP_OPTIMIZATION_PHOTO;
+
+ m_SceneMode = KSCAMERA_EXTENDEDPROP_SCENEMODE_AUTO;
+
+ // Wipe the global settings to zeros for now.
+ RtlFillBytes(&m_GlobalIspSettings, sizeof(m_GlobalIspSettings), 0);
+
+ m_GlobalIspSettings.FlashMode = KSCAMERA_EXTENDEDPROP_FLASH_OFF;
+ m_GlobalIspSettings.FlashValue = 50;
+
+ m_GlobalIspSettings.ISOMode = KSCAMERA_EXTENDEDPROP_ISO_AUTO;
+ m_GlobalIspSettings.ISOValue = 200;
+
+ m_GlobalIspSettings.EVCompensation.Mode = 0;
+ m_GlobalIspSettings.EVCompensation.Min = -2;
+ m_GlobalIspSettings.EVCompensation.Max = 2;
+ m_GlobalIspSettings.EVCompensation.Value = 0;
+ m_GlobalIspSettings.EVCompensation.Mode = KSCAMERA_EXTENDEDPROP_EVCOMP_FULLSTEP;
+
+ m_GlobalIspSettings.WhiteBalanceMode = KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO;
+ m_GlobalIspSettings.WhiteBalanceSetting.Max = WHITEBALANCE_MAX;
+ m_GlobalIspSettings.WhiteBalanceSetting.Min = WHITEBALANCE_MIN;
+ m_GlobalIspSettings.WhiteBalanceSetting.Step = WHITEBALANCE_STEP;
+ m_GlobalIspSettings.WhiteBalanceSetting.Reserved = 0;
+ m_GlobalIspSettings.WhiteBalanceSetting.VideoProc.Value.ul = WhiteBalanceDefault;
+ m_GlobalIspSettings.WhiteBalanceSetting.Mode = KSCAMERA_EXTENDEDPROP_WHITEBALANCE_TEMPERATURE;
+
+ m_GlobalIspSettings.ExposureMode = KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO;
+ m_GlobalIspSettings.ExposureSetting.Max = (MAX_EXPOSURE_TIME>LONG_MAX) ? LONG_MAX : (LONG)(LONG_MAX & MAX_EXPOSURE_TIME);
+ m_GlobalIspSettings.ExposureSetting.Min = (LONG)MIN_EXPOSURE_TIME;
+ m_GlobalIspSettings.ExposureSetting.Step = 1;
+ m_GlobalIspSettings.ExposureSetting.Reserved = 0;
+ m_GlobalIspSettings.ExposureSetting.VideoProc.Value.ll = DEF_EXPOSURE_TIME;
+ m_GlobalIspSettings.ExposureSetting.Mode = 0;
+
+ m_GlobalIspSettings.FocusMode = KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS | KSCAMERA_EXTENDEDPROP_FOCUS_RANGE_FULLRANGE;
+ m_GlobalIspSettings.FocusSetting.Max = 1200;
+ m_GlobalIspSettings.FocusSetting.Min = 1;
+ m_GlobalIspSettings.FocusSetting.Step = 1;
+ m_GlobalIspSettings.FocusSetting.Reserved = 0;
+ m_GlobalIspSettings.FocusSetting.VideoProc.Value.ul = 100;
+ m_GlobalIspSettings.FocusSetting.Mode = 0;
+ m_GlobalIspSettings.FocusPriority = KSCAMERA_EXTENDEDPROP_FOCUSPRIORITY_ON;
+
+ m_GlobalIspSettings.bPhotoConfirmation = TRUE;
+
+ // Defaults to fall back to if we get a cancel.
+ m_LastFocusMode = KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS | KSCAMERA_EXTENDEDPROP_FOCUS_RANGE_FULLRANGE;
+ m_LastFocusSetting = 100;
+
+
+ // Specifies the dynamic range of our fictious camera's lens system
+ // Note: Magnification = Lobjective / Locular
+
+ // The following values set only the minimum and maximum for the rational number expressing the zoom.
+
+ // This specifies the denominator of the rational value used to specify magnification.
+ m_FocalLength.lOcularFocalLength = FOCALLENGTH_OCULAR;
+ // If lObjectiveFocalLengthMin < lOcularFocalLength, then camera allows Zoom out: aka, wide-field view.
+ m_FocalLength.lObjectiveFocalLengthMin = FOCALLENGTH_OPTICAL_MIN;
+ // If lObjectiveFocalLengthMax > lOcularFocalLength, then camera allows Zoom in: aka, Magnified, narrow-field view.
+ m_FocalLength.lObjectiveFocalLengthMax = FOCALLENGTH_OPTICAL_MAX;
+
+ // Cache values for the new extended zoom property.
+ m_ExtendedZoom.Flags = KSCAMERA_EXTENDEDPROP_ZOOM_DIRECT;
+ m_ExtendedZoom.Min() = (LONG)(TO_Q16(FOCALLENGTH_OPTICAL_MIN) / FOCALLENGTH_OCULAR);
+ m_ExtendedZoom.Max() = (LONG)(TO_Q16(FOCALLENGTH_OPTICAL_MAX) / FOCALLENGTH_OCULAR);
+ m_ExtendedZoom.Step() = 1; // This avoids the rounding issue.
+ m_ExtendedZoom = ZoomDefault;
+ //TO_Q16(ZoomRangeAndStep[0].SteppingDelta) / FOCALLENGTH_OCULAR;
+
+ // Set up our current zoom.
+ m_Zoom.Capabilities =
+ KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL |
+ KSPROPERTY_CAMERACONTROL_FLAGS_AUTO |
+ KSPROPERTY_CAMERACONTROL_FLAGS_ABSOLUTE |
+ KSPROPERTY_CAMERACONTROL_FLAGS_RELATIVE;
+ m_Zoom.Value = ZoomDefault;
+ m_Zoom.Flags = KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL | KSPROPERTY_CAMERACONTROL_FLAGS_ABSOLUTE;
+
+ // Set up our relative zoom.
+ m_ZoomRelative.Capabilities =
+ KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL |
+ KSPROPERTY_CAMERACONTROL_FLAGS_AUTO |
+ KSPROPERTY_CAMERACONTROL_FLAGS_ABSOLUTE;
+ m_ZoomRelative.Value = ZoomRelativeDefault;
+ m_ZoomRelative.Flags = KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL | KSPROPERTY_CAMERACONTROL_FLAGS_ABSOLUTE;
+
+ m_Pan.Capabilities =
+ KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL |
+ KSPROPERTY_CAMERACONTROL_FLAGS_AUTO |
+ KSPROPERTY_CAMERACONTROL_FLAGS_ABSOLUTE;
+ m_Pan.Value = PanDefault;
+ m_Pan.Flags = KSPROPERTY_CAMERACONTROL_FLAGS_AUTO | KSPROPERTY_CAMERACONTROL_FLAGS_ABSOLUTE;
+
+ m_Roll.Capabilities =
+ KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL |
+ KSPROPERTY_CAMERACONTROL_FLAGS_AUTO |
+ KSPROPERTY_CAMERACONTROL_FLAGS_ABSOLUTE;
+ m_Roll.Value = RollDefault;
+ m_Roll.Flags = KSPROPERTY_CAMERACONTROL_FLAGS_AUTO | KSPROPERTY_CAMERACONTROL_FLAGS_ABSOLUTE;
+
+ m_Tilt.Capabilities =
+ KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL |
+ KSPROPERTY_CAMERACONTROL_FLAGS_AUTO |
+ KSPROPERTY_CAMERACONTROL_FLAGS_ABSOLUTE;
+ m_Tilt.Value = TiltDefault;
+ m_Tilt.Flags = KSPROPERTY_CAMERACONTROL_FLAGS_AUTO | KSPROPERTY_CAMERACONTROL_FLAGS_ABSOLUTE;
+
+ m_BacklightCompensation.Capabilities =
+ KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL |
+ KSPROPERTY_VIDEOPROCAMP_FLAGS_AUTO;
+ m_BacklightCompensation.Value = BacklightCompensationDefault;
+ m_BacklightCompensation.Flags = KSPROPERTY_CAMERACONTROL_FLAGS_AUTO;
+
+ m_Brightness.Capabilities =
+ KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL |
+ KSPROPERTY_VIDEOPROCAMP_FLAGS_AUTO;
+ m_Brightness.Value = BrightnessDefault;
+ m_Brightness.Flags = KSPROPERTY_CAMERACONTROL_FLAGS_AUTO;
+
+ m_Contrast.Capabilities =
+ KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL |
+ KSPROPERTY_VIDEOPROCAMP_FLAGS_AUTO;
+ m_Contrast.Value = ContrastDefault;
+ m_Contrast.Flags = KSPROPERTY_CAMERACONTROL_FLAGS_AUTO;
+
+ m_Hue.Capabilities =
+ KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL |
+ KSPROPERTY_VIDEOPROCAMP_FLAGS_AUTO;
+ m_Hue.Value = HueDefault;
+ m_Hue.Flags = KSPROPERTY_CAMERACONTROL_FLAGS_AUTO;
+
+ // Set up our Power Line Frequency defaults.
+ m_PowerLineFreq.Capabilities =
+ KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL | KSPROPERTY_CAMERACONTROL_FLAGS_AUTO;
+ m_PowerLineFreq.Value = POWERLINEFREQ_DEFAULT;
+ m_PowerLineFreq.Flags = KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL;
+
+ m_IsoResult = STATUS_SUCCESS;
+ m_EvCompResult = STATUS_SUCCESS;
+ m_WhiteBalanceResult= STATUS_SUCCESS;
+ m_ExposureResult = STATUS_SUCCESS;
+ m_SceneModeResult = STATUS_SUCCESS;
+ m_FaceDetectionResult = STATUS_SUCCESS;
+ m_FocusResult = STATUS_SUCCESS;
+
+ for( ULONG PinIndex=0; PinIndex<GetPinCount(); PinIndex++ )
+ {
+ // Reset the metadata control.
+ m_MetadataInfo[PinIndex] = CExtendedMetadata(PinIndex);
+
+ // Reset the warmstart control.
+ m_WarmStartEnabled[PinIndex] = CExtendedProperty(KSCAMERA_EXTENDEDPROP_WARMSTART_MODE_DISABLED);
+ m_WarmStartEnabled[PinIndex].PinId = PinIndex;
+ }
+
+ DBG_LEAVE("()");
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+CSensorSimulation::
+Initialize()
+/*++
+
+Routine Description:
+
+ Perform memory allocations for the simulation. Inspect the descriptors
+ for pins and allocate appropriate simulation objects based on the pin's
+ type.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ Success / Failure
+
+--*/
+{
+ PAGED_CODE();
+
+ DBG_ENTER("()");
+ NTSTATUS Status = STATUS_SUCCESS;
+ IFFAILED_EXIT( Status = CSensor::Initialize() );
+
+ IFNULL_EXIT( m_FocusTimer = new (NonPagedPoolNx, 'emiT') KPassiveTimer( m_Device->GetDeviceObject() ) );
+ IFNULL_EXIT( m_FocusRectTimer = new (NonPagedPoolNx, 'emiT') KPassiveTimer( m_Device->GetDeviceObject() ) );
+ IFNULL_EXIT( m_MetadataInfo = new (PagedPool, 'ateM') CExtendedMetadata[GetPinCount()] );
+ IFNULL_EXIT( m_WarmStartEnabled = new (PagedPool, 'mraW' ) CExtendedProperty[GetPinCount()] );
+
+ for( ULONG PinIndex=0;
+ NT_SUCCESS(Status) && PinIndex<m_Descriptors->PinDescriptorsCount;
+ PinIndex++ )
+ {
+ const KSPIN_DESCRIPTOR_EX *PinDescriptors = m_Descriptors->PinDescriptors;
+ CHardwareSimulation *pSim=nullptr;
+
+ NT_ASSERT( m_Descriptors->PinDescriptorSize == sizeof( *PinDescriptors ) );
+
+ // Video pin type
+ if( IsEqualGUID( *PinDescriptors[PinIndex].PinDescriptor.Category, PIN_CATEGORY_CAPTURE ) )
+ {
+ pSim = new (NonPagedPoolNx, 'ediV') CVideoHardwareSimulation( this, PinIndex );
+ m_VideoMask |= 1<<PinIndex;
+ }
+ else if( IsEqualGUID( *PinDescriptors[PinIndex].PinDescriptor.Category, PIN_CATEGORY_PREVIEW ) )
+ {
+ pSim = new (NonPagedPoolNx, 'verP') CPreviewHardwareSimulation( this, PinIndex );
+ m_PreviewMask |= 1<<PinIndex; // must set to enable photo confirmation...
+ }
+ else if( IsEqualGUID( *PinDescriptors[PinIndex].PinDescriptor.Category, PINNAME_IMAGE ) )
+ {
+ pSim = new (NonPagedPoolNx, 'litS') CImageHardwareSimulation( this, PinIndex );
+ m_StillMask |= 1<<PinIndex;
+ }
+ else
+ {
+ // We don't know this pin type, so skip it.
+ m_HardwareSimulation[PinIndex] = nullptr;
+ continue;
+ }
+
+ if( pSim )
+ {
+ if( pSim->Initialize() )
+ {
+ m_HardwareSimulation[PinIndex] = pSim;
+ }
+ else
+ {
+ //
+ // If we couldn't create the hardware simulation, fail.
+ //
+ delete pSim;
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+ else
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+
+done:
+ DBG_ENTER("()=0x%08X", Status);
+ return Status;
+}
+
+/**************************************************************************
+
+ Sensor-level control simulations
+
+ 1. Query capabilities and state of the device.
+ 2. Issue a command or set state on the device.
+
+**************************************************************************/
+
+// Get for KSPROPERTY_CAMERACONTROL_REGION_OF_INTEREST_PROPERTY_ID
+NTSTATUS
+CSensorSimulation::
+GetFocusRect(
+ _Inout_ PKSPROPERTY_CAMERACONTROL_REGION_OF_INTEREST_S pRoi
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ pRoi->FocusRect = m_FocusRect;
+ pRoi->AutoFocusLock = m_AutoFocusLock;
+ pRoi->AutoExposureLock = m_AutoExposureLock;
+ pRoi->AutoWhitebalanceLock = m_AutoWhitebalanceLock;
+ pRoi->Capabilities = KSPROPERTY_CAMERACONTROL_REGION_OF_INTEREST_FLAGS_AUTO | KSPROPERTY_CAMERACONTROL_REGION_OF_INTEREST_FLAGS_MANUAL |
+ KSPROPERTY_CAMERACONTROL_REGION_OF_INTEREST_FLAGS_ASYNC | KSPROPERTY_CAMERACONTROL_REGION_OF_INTEREST_CONFIG_FOCUS |
+ KSPROPERTY_CAMERACONTROL_REGION_OF_INTEREST_CONFIG_EXPOSURE;
+ return STATUS_SUCCESS;
+}
+
+// Set for KSPROPERTY_CAMERACONTROL_REGION_OF_INTEREST_PROPERTY_ID
+NTSTATUS
+CSensorSimulation::
+SetFocusRectAsync(
+ _In_ PKSPROPERTY_CAMERACONTROL_REGION_OF_INTEREST_S pRoi,
+ _In_ CNotifier *Notifier // Use to notify the framework that the control is done.
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ if( m_FocusRectNotifier )
+ {
+ // The last operation is still pending.
+ return STATUS_INVALID_DEVICE_STATE;
+ }
+
+ m_FocusRectNotifier = Notifier;
+
+ m_FocusRect = pRoi->FocusRect;
+ m_AutoFocusLock = pRoi->AutoFocusLock;
+ m_AutoExposureLock = pRoi->AutoExposureLock;
+ m_AutoWhitebalanceLock = pRoi->AutoWhitebalanceLock;
+
+ if(m_AutoFocusLock)
+ {
+ m_GlobalIspSettings.FocusMode = KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO;
+ m_GlobalIspSettings.FocusSetting.VideoProc.Value.ul = 100;
+ }
+ if(m_AutoExposureLock)
+ {
+ m_GlobalIspSettings.ExposureMode = KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO;
+ m_GlobalIspSettings.ExposureSetting.VideoProc.Value.ll = DEF_EXPOSURE_TIME;
+ DBG_TRACE("ExposureMode=KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO, ExposureTime=%lld00ns",
+ m_GlobalIspSettings.ExposureSetting.VideoProc.Value.ll);
+ }
+ if(m_AutoWhitebalanceLock)
+ {
+ m_GlobalIspSettings.WhiteBalanceMode = KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO;
+ m_GlobalIspSettings.WhiteBalanceSetting.VideoProc.Value.ul = WhiteBalanceDefault;
+ m_GlobalIspSettings.WhiteBalanceSetting.Mode = KSCAMERA_EXTENDEDPROP_WHITEBALANCE_TEMPERATURE;
+ }
+
+ // Fire a one-shot timer to transition the focus state.
+ m_FocusTimer->Set(
+ -2500000LL, // 250ms
+ FocusRectConvergence,
+ this );
+
+ return STATUS_SUCCESS;
+}
+
+// Cancel an outstanding KSPROPERTY_CAMERACONTROL_REGION_OF_INTEREST_PROPERTY_ID Set
+NTSTATUS
+CSensorSimulation::
+CancelFocusRect()
+{
+ PAGED_CODE();
+
+ // Per spec, this control cannot be cancelled. So we block until complete.
+ // Even if we didn't block here, the CNotifier object is reference counted,
+ // so the CCaptureFilter would block until the operation completes.
+ if( m_FocusRectNotifier )
+ {
+ m_FocusRectTimer->Wait();
+ }
+ return STATUS_UNSUCCESSFUL;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_FACEDETECTION.
+NTSTATUS
+CSensorSimulation::
+GetFaceDetection(
+ _Inout_ CExtendedVidProcSetting *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ *pProperty = CExtendedVidProcSetting( m_FaceDetectionFlags );
+
+ pProperty->Capability =
+ KSCAMERA_EXTENDEDPROP_FACEDETECTION_OFF |
+ KSCAMERA_EXTENDEDPROP_FACEDETECTION_PREVIEW |
+ KSCAMERA_EXTENDEDPROP_FACEDETECTION_VIDEO |
+ KSCAMERA_EXTENDEDPROP_FACEDETECTION_PHOTO |
+ KSCAMERA_EXTENDEDPROP_FACEDETECTION_BLINK |
+ KSCAMERA_EXTENDEDPROP_FACEDETECTION_SMILE ;
+
+ pProperty->Max() = m_FaceDetectionMax;
+ pProperty->Min() = 1;
+ pProperty->Step() = 1;
+ *pProperty = m_FaceDetectionCurrentMax;
+ pProperty->Result = m_FaceDetectionResult;
+
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_FACEDETECTION.
+NTSTATUS
+CSensorSimulation::
+SetFaceDetection(
+ _In_ CExtendedVidProcSetting *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ m_FaceDetectionCurrentMax =
+ ( KSCAMERA_EXTENDEDPROP_FACEDETECTION_MASK & pProperty->Flags ) ?
+ pProperty->GetULONG() : 0;
+ m_FaceDetectionFlags = pProperty->Flags;
+ m_FaceDetectionResult = STATUS_SUCCESS;
+ return STATUS_SUCCESS;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_FOCUSSTATE
+NTSTATUS
+CSensorSimulation::
+GetFocusState(
+ _Out_ KSCAMERA_EXTENDEDPROP_FOCUSSTATE *FocusState
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ *FocusState = m_FocusState;
+
+ DBG_LEAVE("(%s)", FocusStateDbgTxt(m_FocusState));
+ return STATUS_SUCCESS;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_FOCUSMODE
+NTSTATUS
+CSensorSimulation::
+GetFocus(
+ _Inout_ CExtendedVidProcSetting *pSetting
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ // Mode
+ pSetting->Flags = m_GlobalIspSettings.FocusMode;
+
+ // capabilities.
+ pSetting->Capability = KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL |
+ KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO |
+ KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK |
+ KSCAMERA_EXTENDEDPROP_FOCUS_UNLOCK |
+ KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL |
+ KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS |
+ KSCAMERA_EXTENDEDPROP_CAPS_CANCELLABLE |
+ KSCAMERA_EXTENDEDPROP_FOCUS_RANGE_MACRO |
+ KSCAMERA_EXTENDEDPROP_FOCUS_RANGE_NORMAL |
+ KSCAMERA_EXTENDEDPROP_FOCUS_RANGE_FULLRANGE |
+ KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUSLOCK |
+ KSCAMERA_EXTENDEDPROP_FOCUS_REGIONBASED |
+ KSCAMERA_EXTENDEDPROP_FOCUS_DRIVERFALLBACK_OFF |
+ KSCAMERA_EXTENDEDPROP_FOCUS_DISTANCE_INFINITY |
+ KSCAMERA_EXTENDEDPROP_FOCUS_DISTANCE_HYPERFOCAL |
+ KSCAMERA_EXTENDEDPROP_FOCUS_DISTANCE_NEAREST
+ ;
+
+ pSetting->Result = m_FocusResult;
+
+ // min/max/step/etc.
+ pSetting->m_Setting = m_GlobalIspSettings.FocusSetting;
+
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_FOCUSMODE
+NTSTATUS
+CSensorSimulation::
+SetFocusAsync(
+ _In_ CExtendedVidProcSetting *pSetting,
+ _In_ CNotifier *Notifier // Use to notify the framework that the control is done.
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ // Signal immediately if the we are continuous focus.
+ bool bSignalImmediately = false;
+ ULONGLONG Flags = pSetting->Flags;
+
+ // Cache our current focus settings in case we get a cancel request.
+ m_LastFocusMode = m_GlobalIspSettings.FocusMode;
+ m_LastFocusSetting = m_GlobalIspSettings.FocusSetting.VideoProc.Value.ul;
+
+ // If we've been asked to unlock, remove any lock flags.
+ if( Flags & KSCAMERA_EXTENDEDPROP_FOCUS_UNLOCK )
+ {
+ // Mark us as signalling immediately if Focus was not locked.
+ bSignalImmediately =
+ ( m_GlobalIspSettings.FocusMode &
+ ( KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK |
+ KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUSLOCK ) ) == 0;
+
+ // Change our operation so we go back to the previous state.
+ Flags = m_GlobalIspSettings.FocusMode &
+ ~( KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK |
+ KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUSLOCK );
+ }
+
+ // Handle the stand-alone lock case by setting the appropriate flags.
+ if( ( Flags &
+ (KSCAMERA_EXTENDEDPROP_FOCUS_MODE_MASK |
+ KSCAMERA_EXTENDEDPROP_FOCUS_MODE_ADVANCED_MASK) ) ==
+ KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK )
+ {
+ if( m_GlobalIspSettings.FocusMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO )
+ {
+ Flags =
+ m_GlobalIspSettings.FocusMode | KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK;
+ }
+ if( m_GlobalIspSettings.FocusMode & KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS )
+ {
+ Flags =
+ m_GlobalIspSettings.FocusMode |= KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUSLOCK;
+ }
+ }
+
+ // Record the Focus mode.
+ DBG_TRACE("Recording FocusMode = 0x%016llX", Flags);
+ m_GlobalIspSettings.FocusMode = Flags;
+
+ if(m_GlobalIspSettings.FocusMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL)
+ {
+ m_GlobalIspSettings.FocusSetting.VideoProc.Value.l = pSetting->GetLONG();
+ }
+
+ if( bSignalImmediately )
+ // Unlock, but nothing really to do.
+ {
+ Notifier->Set();
+ m_FocusNotifier = nullptr;
+ }
+ else if( Flags & KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS )
+ // Continuous case: Signal immediately.
+ // Then prime the timer to switch the state to focused.
+ {
+ m_FocusNotifier = nullptr;
+ m_FocusState = KSCAMERA_EXTENDEDPROP_FOCUSSTATE_SEARCHING;
+ Notifier->Set();
+
+ // Fire a one-shot timer to transition the focus state.
+ m_FocusTimer->Set(
+ -4000000LL, // 400ms
+ FocusConvergence,
+ this );
+ }
+ else if( Flags & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO )
+ // Normal [auto?] focus operation.
+ // Autofocus should be SLOW.
+ {
+ m_FocusNotifier = Notifier;
+ m_FocusState = KSCAMERA_EXTENDEDPROP_FOCUSSTATE_SEARCHING;
+
+ // Fire a one-shot timer to transition the focus state.
+ m_FocusTimer->Set(
+ -4000000LL, // 400ms
+ FocusConvergence,
+ this );
+ }
+ else
+ // Handle Manual, lock & unlock cases FAST ~1 frame time.
+ {
+ m_FocusNotifier = Notifier;
+ m_FocusState = KSCAMERA_EXTENDEDPROP_FOCUSSTATE_SEARCHING;
+
+ // Fire a one-shot timer to transition the focus state.
+ m_FocusTimer->Set(
+ -330000LL, // 33ms
+ FocusConvergence,
+ this );
+ }
+
+ m_FocusResult = STATUS_SUCCESS;
+ return STATUS_SUCCESS;
+}
+
+// Cancel oustanding set KSPROPERTY_CAMERACONTROL_EXTENDED_FOCUSMODE
+NTSTATUS
+CSensorSimulation::
+CancelFocus()
+{
+ PAGED_CODE();
+
+ // Cancel our timer to prevent a race.
+ m_FocusTimer->Cancel();
+
+ // Acquire the lock after the cancel to avoid a potential deadlock.
+ KScopedMutex lock( m_SensorMutex );
+
+ // Now check to see if an operation was still outstanding.
+ // We could just check the status from the timer's Cancel(), but I
+ // prefer checking to see if the handler cleared the notifier instead.
+ if( m_FocusNotifier )
+ {
+ m_FocusState = KSCAMERA_EXTENDEDPROP_FOCUSSTATE_LOST;
+
+ // Cancel behavior isn't well-defined in the spec. Do something reasonable.
+ // In our case, we'll put the focus mode and value back to the last setting.
+ m_GlobalIspSettings.FocusMode = m_LastFocusMode;
+ m_GlobalIspSettings.FocusSetting.VideoProc.Value.ul = m_LastFocusSetting;
+
+ m_FocusNotifier->Set();
+ m_FocusNotifier = nullptr;
+ m_FocusResult = (ULONG) STATUS_CANCELLED;
+ return STATUS_SUCCESS;
+ }
+ return STATUS_UNSUCCESSFUL;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_FLASHMODE
+NTSTATUS
+CSensorSimulation::
+GetExtendedFlash(
+ _Inout_ CExtendedProperty *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ *pProperty = CExtendedProperty( m_GlobalIspSettings.FlashMode );
+ *pProperty = m_GlobalIspSettings.FlashValue;
+ pProperty->Capability = KSCAMERA_EXTENDEDPROP_FLASH_ON | KSCAMERA_EXTENDEDPROP_FLASH_ON_ADJUSTABLEPOWER |
+ KSCAMERA_EXTENDEDPROP_FLASH_AUTO | KSCAMERA_EXTENDEDPROP_FLASH_AUTO_ADJUSTABLEPOWER |
+ KSCAMERA_EXTENDEDPROP_FLASH_REDEYEREDUCTION | KSCAMERA_EXTENDEDPROP_FLASH_SINGLEFLASH |
+ KSCAMERA_EXTENDEDPROP_FLASH_MULTIFLASHSUPPORTED |
+ KSCAMERA_EXTENDEDPROP_FLASH_ASSISTANT_ON | KSCAMERA_EXTENDEDPROP_FLASH_ASSISTANT_OFF |
+ KSCAMERA_EXTENDEDPROP_FLASH_ASSISTANT_AUTO
+ ;
+
+ DBG_TRACE("FlashMode=0x%016llX, FlashValue=%d",
+ m_GlobalIspSettings.FlashMode,
+ m_GlobalIspSettings.FlashValue );
+
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_FLASHMODE
+NTSTATUS
+CSensorSimulation::
+SetExtendedFlash(
+ _In_ CExtendedProperty *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ if(pProperty->Flags & (KSCAMERA_EXTENDEDPROP_FLASH_ON_ADJUSTABLEPOWER |
+ KSCAMERA_EXTENDEDPROP_FLASH_AUTO_ADJUSTABLEPOWER) )
+ {
+ m_GlobalIspSettings.FlashValue = pProperty->m_Value.Value.ul;
+ }
+ else
+ {
+ m_GlobalIspSettings.FlashValue = 50;
+ }
+
+ m_GlobalIspSettings.FlashMode = pProperty->Flags;
+ NTSTATUS Status = SetFlashStatus(pProperty->Flags);
+
+ DBG_TRACE("FlashMode=0x%016llX, FlashValue=%d, Status=0x%08X",
+ m_GlobalIspSettings.FlashMode,
+ m_GlobalIspSettings.FlashValue,
+ Status );
+
+ pProperty->Result = (ULONG) Status;
+ return Status;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_ISO
+NTSTATUS
+CSensorSimulation::
+GetIso(
+ _Inout_ CExtendedProperty *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ pProperty->Flags = IsoModeValue2Preset(
+ m_GlobalIspSettings.ISOMode,
+ m_GlobalIspSettings.ISOValue );
+ pProperty->Result = STATUS_SUCCESS;
+ pProperty->Capability = KSCAMERA_EXTENDEDPROP_ISO_AUTO |
+ KSCAMERA_EXTENDEDPROP_ISO_50 | KSCAMERA_EXTENDEDPROP_ISO_80 |
+ KSCAMERA_EXTENDEDPROP_ISO_100 | KSCAMERA_EXTENDEDPROP_ISO_200 |
+ KSCAMERA_EXTENDEDPROP_ISO_400 | KSCAMERA_EXTENDEDPROP_ISO_800 |
+ KSCAMERA_EXTENDEDPROP_ISO_1600 | KSCAMERA_EXTENDEDPROP_ISO_3200 |
+ KSCAMERA_EXTENDEDPROP_ISO_6400 | KSCAMERA_EXTENDEDPROP_ISO_12800 |
+ KSCAMERA_EXTENDEDPROP_ISO_25600 |
+ KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL;
+ pProperty->Result = m_IsoResult;
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_ISO
+NTSTATUS
+CSensorSimulation::
+SetIsoAsync(
+ _In_ CExtendedProperty *pProperty,
+ _In_ CNotifier *Notifier // Use to notify the framework that the control is done.
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ m_GlobalIspSettings.ISOMode = (ULONG)pProperty->Flags;
+ m_GlobalIspSettings.ISOValue = 0;
+
+ // This could be done in a separate work item after the scene mode has been programmed...
+ m_IsoResult = STATUS_SUCCESS;
+ Notifier->Set();
+
+ return STATUS_SUCCESS;
+}
+
+#define KSCAMERA_EXTENDEDPROP_ISO_ADVANCED_MASK (KSCAMERA_EXTENDEDPROP_ISO_AUTO | KSCAMERA_EXTENDEDPROP_ISO_MANUAL)
+
+// Create a set of default settings...
+static
+const
+KSCAMERA_EXTENDEDPROP_VIDEOPROCSETTING g_IsoAdvancedSettings =
+{
+ 0, // Mode - Unused
+ 50, // Min
+ 25600, // Max
+ 1 // Step (advertised doesn't have to be actual)
+};
+
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_ISO_ADVANCED.
+NTSTATUS
+CSensorSimulation::
+GetIsoAdvanced(
+ _Inout_ CExtendedVidProcSetting *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ // Initialize the property with defaults + (AUTO | MANUAL)
+ pProperty->Flags =
+ m_GlobalIspSettings.ISOMode &
+ KSCAMERA_EXTENDEDPROP_ISO_ADVANCED_MASK;
+ pProperty->Result = STATUS_SUCCESS;
+
+ // Advertise basic caps...
+ pProperty->Capability =
+ KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL |
+ KSCAMERA_EXTENDEDPROP_ISO_AUTO |
+ KSCAMERA_EXTENDEDPROP_ISO_MANUAL ;
+
+ // Advertise the manual caps...
+ *pProperty = g_IsoAdvancedSettings;
+
+ // If ISO is MANUAL, set the value.
+ if( m_GlobalIspSettings.ISOMode == KSCAMERA_EXTENDEDPROP_ISO_MANUAL )
+ {
+ *pProperty = m_GlobalIspSettings.ISOValue;
+ }
+ else if( !(m_GlobalIspSettings.ISOMode == KSCAMERA_EXTENDEDPROP_ISO_AUTO) )
+ {
+ // Try converting any legacy presets to a manual value.
+ pProperty->Flags = KSCAMERA_EXTENDEDPROP_ISO_MANUAL;
+ // Convert the ISO setting
+ *pProperty = IsoPreset2Value( m_GlobalIspSettings.ISOMode );
+ // If we weren't able to report a valid number, just report something reasonable...
+ if( pProperty->GetLONG() > pProperty->Max() )
+ {
+ *pProperty = pProperty->Min();
+ }
+ }
+ pProperty->Result = m_IsoResult;
+
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_ISO_ADVANCED.
+NTSTATUS
+CSensorSimulation::
+SetIsoAdvancedAsync(
+ _In_ CExtendedVidProcSetting *pProperty,
+ _In_ CNotifier *Notifier // Use to notify the framework that the control is done.
+)
+{
+ PAGED_CODE();
+
+ KScopedMutex lock( m_SensorMutex );
+
+ // Just save the parameters
+ if( pProperty->Flags & KSCAMERA_EXTENDEDPROP_ISO_MANUAL )
+ {
+ m_GlobalIspSettings.ISOMode = pProperty->Flags;
+ m_GlobalIspSettings.ISOValue= pProperty->GetULONG();
+ }
+ else if( pProperty->Flags & KSCAMERA_EXTENDEDPROP_ISO_AUTO )
+ {
+ m_GlobalIspSettings.ISOMode = pProperty->Flags;
+ }
+
+ // Set regardless - it takes effect immediately for us.
+ m_IsoResult = STATUS_SUCCESS;
+ Notifier->Set();
+
+ return STATUS_SUCCESS;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_EVCOMPENSATION
+NTSTATUS
+CSensorSimulation::
+GetEvCompensation(
+ _Inout_ CExtendedEvCompensation *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ *pProperty = CExtendedEvCompensation( m_GlobalIspSettings.EVCompensation.Mode );
+
+ // Return our cached copy; but update the value from the global setting.
+ *pProperty = m_GlobalIspSettings.EVCompensation;
+ pProperty->Capability = KSCAMERA_EXTENDEDPROP_EVCOMP_SIXTHSTEP | KSCAMERA_EXTENDEDPROP_EVCOMP_QUARTERSTEP |
+ KSCAMERA_EXTENDEDPROP_EVCOMP_THIRDSTEP | KSCAMERA_EXTENDEDPROP_EVCOMP_HALFSTEP |
+ KSCAMERA_EXTENDEDPROP_EVCOMP_FULLSTEP | KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL;
+ pProperty->Result = m_EvCompResult;
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_EVCOMPENSATION
+NTSTATUS
+CSensorSimulation::
+SetEvCompensationAsync(
+ _In_ CExtendedEvCompensation *pProperty,
+ _In_ CNotifier *Notifier // Use to notify the framework that the control is done.
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ // Update the Globals
+ m_GlobalIspSettings.EVCompensation.Mode = (ULONG) pProperty->Flags;
+ m_GlobalIspSettings.EVCompensation.Value = pProperty->Value();
+
+ // Update the current setting in case we're queried for it later.
+ m_GlobalIspSettings.EVCompensation.Value = pProperty->Value();
+
+ // This could be done in a separate work item after the device has been programmed...
+ m_EvCompResult = STATUS_SUCCESS;
+ Notifier->Set();
+
+ return STATUS_SUCCESS;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_WHITEBALANCEMODE
+NTSTATUS
+CSensorSimulation::
+GetWhiteBalance(
+ _Inout_ CExtendedVidProcSetting *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ *pProperty = CExtendedVidProcSetting( m_GlobalIspSettings.WhiteBalanceMode );
+
+ // Return our cached copy; but update the value from the global setting.
+ *pProperty = m_GlobalIspSettings.WhiteBalanceSetting;
+ pProperty->Capability = KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL | KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO |
+ KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK | KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL;
+ pProperty->Result = m_WhiteBalanceResult;
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_WHITEBALANCEMODE
+NTSTATUS
+CSensorSimulation::
+SetWhiteBalanceAsync(
+ _In_ CExtendedVidProcSetting *pProperty,
+ _In_ CNotifier *Notifier // Use to notify the framework that the control is done.
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ m_GlobalIspSettings.WhiteBalanceMode = pProperty->Flags;
+ m_GlobalIspSettings.WhiteBalanceSetting.Mode = pProperty->Mode();
+ m_GlobalIspSettings.WhiteBalanceSetting.VideoProc.Value.ul = pProperty->GetULONG();
+
+ // This could be done in a separate work item after the device has been programmed...
+ m_WhiteBalanceResult = STATUS_SUCCESS;
+ Notifier->Set();
+
+ return STATUS_SUCCESS;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_EXPOSURE
+NTSTATUS
+CSensorSimulation::
+GetExposure(
+ _Inout_ CExtendedVidProcSetting *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ *pProperty = CExtendedVidProcSetting( m_GlobalIspSettings.ExposureMode );
+
+ // Return our cached copy; but update the value from the global setting.
+ *pProperty = m_GlobalIspSettings.ExposureSetting;
+ pProperty->Capability = KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL | KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO |
+ KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK | KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL;
+ pProperty->Result = m_ExposureResult;
+ DBG_TRACE("ExposureMode=0x%016llX, ExposureTime=%lld00ns",
+ pProperty->Flags, pProperty->GetLONGLONG());
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_EXPOSURE
+NTSTATUS
+CSensorSimulation::
+SetExposureAsync(
+ _In_ CExtendedVidProcSetting *pProperty,
+ _In_ CNotifier *Notifier // Use to notify the framework that the control is done.
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ DBG_TRACE("ExposureMode=0x%016llX, ExposureTime=%lld00ns",
+ pProperty->Flags, pProperty->GetLONGLONG());
+ if( pProperty->Flags & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL )
+ {
+ m_GlobalIspSettings.ExposureSetting.VideoProc.Value.ull = pProperty->GetULONGLONG();
+ }
+ m_GlobalIspSettings.ExposureMode = pProperty->Flags;
+
+ // This could be done in a separate work item after the device has been programmed...
+ m_ExposureResult = STATUS_SUCCESS;
+ Notifier->Set();
+
+ return STATUS_SUCCESS;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOCONFIRMATION
+NTSTATUS
+CSensorSimulation::
+GetPhotoConfirmation(
+ _Inout_ CExtendedProperty *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ *pProperty = CExtendedProperty( m_GlobalIspSettings.bPhotoConfirmation );
+ DBG_TRACE( "Is %s", m_GlobalIspSettings.bPhotoConfirmation ? "On" : "Off" );
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOCONFIRMATION
+NTSTATUS
+CSensorSimulation::
+SetPhotoConfirmation(
+ _In_ CExtendedProperty *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ // Return our cached copy; but update the value from the global setting.
+ m_GlobalIspSettings.bPhotoConfirmation =
+ BOOLEAN( (pProperty->Flags & KSCAMERA_EXTENDEDPROP_PHOTOCONFIRMATION_ON)
+ == KSCAMERA_EXTENDEDPROP_PHOTOCONFIRMATION_ON);
+ DBG_TRACE( "Is %s", m_GlobalIspSettings.bPhotoConfirmation ? "On" : "Off" );
+ return STATUS_SUCCESS;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_SCENEMODE
+NTSTATUS
+CSensorSimulation::
+GetSceneMode(
+ _Inout_ CExtendedProperty *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ *pProperty = CExtendedProperty( m_SceneMode );
+ pProperty->Capability = KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL | KSCAMERA_EXTENDEDPROP_SCENEMODE_MACRO |
+ KSCAMERA_EXTENDEDPROP_SCENEMODE_PORTRAIT | KSCAMERA_EXTENDEDPROP_SCENEMODE_SPORT |
+ KSCAMERA_EXTENDEDPROP_SCENEMODE_SNOW | KSCAMERA_EXTENDEDPROP_SCENEMODE_NIGHT |
+ KSCAMERA_EXTENDEDPROP_SCENEMODE_BEACH | KSCAMERA_EXTENDEDPROP_SCENEMODE_SUNSET |
+ KSCAMERA_EXTENDEDPROP_SCENEMODE_CANDLELIGHT | KSCAMERA_EXTENDEDPROP_SCENEMODE_LANDSCAPE |
+ KSCAMERA_EXTENDEDPROP_SCENEMODE_NIGHTPORTRAIT | KSCAMERA_EXTENDEDPROP_SCENEMODE_BACKLIT;
+ pProperty->Result = m_SceneModeResult;
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_SCENEMODE
+NTSTATUS
+CSensorSimulation::
+SetSceneModeAsync(
+ _In_ CExtendedProperty *pProperty,
+ _In_ CNotifier *Notifier // Use to notify the framework that the control is done.
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ m_SceneMode = (ULONG)pProperty->Flags;
+
+ UpdateSettings( m_SceneMode );
+
+ // This could be done in a separate work item after the scene mode has been programmed...
+ m_SceneModeResult = STATUS_SUCCESS;
+ Notifier->Set();
+
+ return STATUS_SUCCESS;
+}
+
+// Apply scene mode changes.
+NTSTATUS
+CSensorSimulation::
+UpdateSettings(
+ _In_ ULONGLONG ullSceneMode
+)
+{
+ PAGED_CODE();
+
+ NTSTATUS status = STATUS_SUCCESS;
+ KScopedMutex lock( m_SensorMutex );
+
+ if( KSCAMERA_EXTENDEDPROP_SCENEMODE_AUTO==ullSceneMode )
+ {
+ //
+ // If the mode was auto, let's randomly replace it with another valid value.
+ //
+ static
+ ULONGLONG ValidModes[] =
+ {
+ KSCAMERA_EXTENDEDPROP_SCENEMODE_MACRO,
+ KSCAMERA_EXTENDEDPROP_SCENEMODE_PORTRAIT, KSCAMERA_EXTENDEDPROP_SCENEMODE_SPORT,
+ KSCAMERA_EXTENDEDPROP_SCENEMODE_SNOW, KSCAMERA_EXTENDEDPROP_SCENEMODE_NIGHT,
+ KSCAMERA_EXTENDEDPROP_SCENEMODE_BEACH, KSCAMERA_EXTENDEDPROP_SCENEMODE_SUNSET,
+ KSCAMERA_EXTENDEDPROP_SCENEMODE_CANDLELIGHT, KSCAMERA_EXTENDEDPROP_SCENEMODE_LANDSCAPE,
+ KSCAMERA_EXTENDEDPROP_SCENEMODE_NIGHTPORTRAIT, KSCAMERA_EXTENDEDPROP_SCENEMODE_BACKLIT
+ };
+
+ ullSceneMode =
+ ValidModes[ (ULONG) (1 << GetRandom( (ULONG)0, SIZEOF_ARRAY(ValidModes)-1 )) ];
+ }
+
+ switch(ullSceneMode)
+ {
+ case KSCAMERA_EXTENDEDPROP_SCENEMODE_MACRO:
+ m_GlobalIspSettings.ISOMode = KSCAMERA_EXTENDEDPROP_ISO_AUTO;
+ m_GlobalIspSettings.EVCompensation.Value = 0;
+ m_GlobalIspSettings.EVCompensation.Mode = KSCAMERA_EXTENDEDPROP_EVCOMP_FULLSTEP;
+ m_GlobalIspSettings.WhiteBalanceSetting.VideoProc.Value.ul = WhiteBalanceDefault;
+ m_GlobalIspSettings.WhiteBalanceSetting.Mode = KSCAMERA_EXTENDEDPROP_WHITEBALANCE_TEMPERATURE;
+ m_GlobalIspSettings.WhiteBalanceMode = KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO;
+ m_GlobalIspSettings.ExposureMode = KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO;
+ m_GlobalIspSettings.ExposureSetting.VideoProc.Value.ul = DEF_EXPOSURE_TIME;
+ m_GlobalIspSettings.ExposureSetting.Mode = 0;
+ m_GlobalIspSettings.FocusMode = KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS | KSCAMERA_EXTENDEDPROP_FOCUS_RANGE_FULLRANGE;
+ m_GlobalIspSettings.FocusSetting.VideoProc.Value.ul = 100;
+ break;
+ case KSCAMERA_EXTENDEDPROP_SCENEMODE_PORTRAIT:
+ m_GlobalIspSettings.ISOMode = KSCAMERA_EXTENDEDPROP_ISO_AUTO;
+ m_GlobalIspSettings.EVCompensation.Value = 0;
+ m_GlobalIspSettings.EVCompensation.Mode = KSCAMERA_EXTENDEDPROP_EVCOMP_FULLSTEP;
+ m_GlobalIspSettings.WhiteBalanceSetting.VideoProc.Value.ul = WhiteBalanceDefault;
+ m_GlobalIspSettings.WhiteBalanceSetting.Mode = KSCAMERA_EXTENDEDPROP_WHITEBALANCE_TEMPERATURE;
+ m_GlobalIspSettings.WhiteBalanceMode = KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO;
+ m_GlobalIspSettings.ExposureMode = KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO;
+ m_GlobalIspSettings.ExposureSetting.VideoProc.Value.ul = DEF_EXPOSURE_TIME;
+ m_GlobalIspSettings.ExposureSetting.Mode = 0;
+ m_GlobalIspSettings.FocusMode = KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS | KSCAMERA_EXTENDEDPROP_FOCUS_RANGE_FULLRANGE;
+ m_GlobalIspSettings.FocusSetting.VideoProc.Value.ul = 100;
+ break;
+ case KSCAMERA_EXTENDEDPROP_SCENEMODE_SPORT:
+ m_GlobalIspSettings.ISOMode = KSCAMERA_EXTENDEDPROP_ISO_AUTO;
+ m_GlobalIspSettings.EVCompensation.Value = 0;
+ m_GlobalIspSettings.EVCompensation.Mode = KSCAMERA_EXTENDEDPROP_EVCOMP_FULLSTEP;
+ m_GlobalIspSettings.WhiteBalanceSetting.VideoProc.Value.ul = WhiteBalanceDefault;
+ m_GlobalIspSettings.WhiteBalanceSetting.Mode = KSCAMERA_EXTENDEDPROP_WHITEBALANCE_TEMPERATURE;
+ m_GlobalIspSettings.WhiteBalanceMode = KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO;
+ m_GlobalIspSettings.ExposureMode = KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO;
+ m_GlobalIspSettings.ExposureSetting.VideoProc.Value.ul = DEF_EXPOSURE_TIME;
+ m_GlobalIspSettings.ExposureSetting.Mode = 0;
+ m_GlobalIspSettings.FocusMode = KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS | KSCAMERA_EXTENDEDPROP_FOCUS_RANGE_FULLRANGE;
+ m_GlobalIspSettings.FocusSetting.VideoProc.Value.ul = 100;
+ break;
+ case KSCAMERA_EXTENDEDPROP_SCENEMODE_SNOW:
+ m_GlobalIspSettings.ISOMode = KSCAMERA_EXTENDEDPROP_ISO_AUTO;
+ m_GlobalIspSettings.EVCompensation.Value = 0;
+ m_GlobalIspSettings.EVCompensation.Mode = KSCAMERA_EXTENDEDPROP_EVCOMP_FULLSTEP;
+ m_GlobalIspSettings.WhiteBalanceSetting.VideoProc.Value.ul = WhiteBalanceDefault;
+ m_GlobalIspSettings.WhiteBalanceSetting.Mode = KSCAMERA_EXTENDEDPROP_WHITEBALANCE_TEMPERATURE;
+ m_GlobalIspSettings.WhiteBalanceMode = KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO;
+ m_GlobalIspSettings.ExposureMode = KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO;
+ m_GlobalIspSettings.ExposureSetting.VideoProc.Value.ul = DEF_EXPOSURE_TIME;
+ m_GlobalIspSettings.ExposureSetting.Mode = 0;
+ m_GlobalIspSettings.FocusMode = KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS | KSCAMERA_EXTENDEDPROP_FOCUS_RANGE_FULLRANGE;
+ m_GlobalIspSettings.FocusSetting.VideoProc.Value.ul = 100;
+ break;
+ case KSCAMERA_EXTENDEDPROP_SCENEMODE_NIGHT:
+ m_GlobalIspSettings.ISOMode = KSCAMERA_EXTENDEDPROP_ISO_AUTO;
+ m_GlobalIspSettings.EVCompensation.Value = 0;
+ m_GlobalIspSettings.EVCompensation.Mode = KSCAMERA_EXTENDEDPROP_EVCOMP_FULLSTEP;
+ m_GlobalIspSettings.WhiteBalanceSetting.VideoProc.Value.ul = WhiteBalanceDefault;
+ m_GlobalIspSettings.WhiteBalanceSetting.Mode = KSCAMERA_EXTENDEDPROP_WHITEBALANCE_TEMPERATURE;
+ m_GlobalIspSettings.WhiteBalanceMode = KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO;
+ m_GlobalIspSettings.ExposureMode = KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO;
+ m_GlobalIspSettings.ExposureSetting.VideoProc.Value.ul = DEF_EXPOSURE_TIME;
+ m_GlobalIspSettings.ExposureSetting.Mode = 0;
+ m_GlobalIspSettings.FocusMode = KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS | KSCAMERA_EXTENDEDPROP_FOCUS_RANGE_FULLRANGE;
+ m_GlobalIspSettings.FocusSetting.VideoProc.Value.ul = 100;
+ break;
+ case KSCAMERA_EXTENDEDPROP_SCENEMODE_BEACH:
+ m_GlobalIspSettings.ISOMode = KSCAMERA_EXTENDEDPROP_ISO_AUTO;
+ m_GlobalIspSettings.EVCompensation.Value = 0;
+ m_GlobalIspSettings.EVCompensation.Mode = KSCAMERA_EXTENDEDPROP_EVCOMP_FULLSTEP;
+ m_GlobalIspSettings.WhiteBalanceSetting.VideoProc.Value.ul = WhiteBalanceDefault;
+ m_GlobalIspSettings.WhiteBalanceSetting.Mode = KSCAMERA_EXTENDEDPROP_WHITEBALANCE_TEMPERATURE;
+ m_GlobalIspSettings.WhiteBalanceMode = KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO;
+ m_GlobalIspSettings.ExposureMode = KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO;
+ m_GlobalIspSettings.ExposureSetting.VideoProc.Value.ul = DEF_EXPOSURE_TIME;
+ m_GlobalIspSettings.ExposureSetting.Mode = 0;
+ m_GlobalIspSettings.FocusMode = KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS | KSCAMERA_EXTENDEDPROP_FOCUS_RANGE_FULLRANGE;
+ m_GlobalIspSettings.FocusSetting.VideoProc.Value.ul = 100;
+ break;
+ case KSCAMERA_EXTENDEDPROP_SCENEMODE_SUNSET:
+ m_GlobalIspSettings.ISOMode = KSCAMERA_EXTENDEDPROP_ISO_AUTO;
+ m_GlobalIspSettings.EVCompensation.Value = 0;
+ m_GlobalIspSettings.EVCompensation.Mode = KSCAMERA_EXTENDEDPROP_EVCOMP_FULLSTEP;
+ m_GlobalIspSettings.WhiteBalanceSetting.VideoProc.Value.ul = WhiteBalanceDefault;
+ m_GlobalIspSettings.WhiteBalanceSetting.Mode = KSCAMERA_EXTENDEDPROP_WHITEBALANCE_TEMPERATURE;
+ m_GlobalIspSettings.WhiteBalanceMode = KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO;
+ m_GlobalIspSettings.ExposureMode = KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO;
+ m_GlobalIspSettings.ExposureSetting.VideoProc.Value.ul = DEF_EXPOSURE_TIME;
+ m_GlobalIspSettings.ExposureSetting.Mode = 0;
+ m_GlobalIspSettings.FocusMode = KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS | KSCAMERA_EXTENDEDPROP_FOCUS_RANGE_FULLRANGE;
+ m_GlobalIspSettings.FocusSetting.VideoProc.Value.ul = 100;
+ break;
+ case KSCAMERA_EXTENDEDPROP_SCENEMODE_CANDLELIGHT:
+ m_GlobalIspSettings.ISOMode = KSCAMERA_EXTENDEDPROP_ISO_AUTO;
+ m_GlobalIspSettings.EVCompensation.Value = 0;
+ m_GlobalIspSettings.EVCompensation.Mode = KSCAMERA_EXTENDEDPROP_EVCOMP_FULLSTEP;
+ m_GlobalIspSettings.WhiteBalanceSetting.VideoProc.Value.ul = WhiteBalanceDefault;
+ m_GlobalIspSettings.WhiteBalanceSetting.Mode = KSCAMERA_EXTENDEDPROP_WHITEBALANCE_TEMPERATURE;
+ m_GlobalIspSettings.WhiteBalanceMode = KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO;
+ m_GlobalIspSettings.ExposureMode = KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO;
+ m_GlobalIspSettings.ExposureSetting.VideoProc.Value.ul = DEF_EXPOSURE_TIME;
+ m_GlobalIspSettings.ExposureSetting.Mode = 0;
+ m_GlobalIspSettings.FocusMode = KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS | KSCAMERA_EXTENDEDPROP_FOCUS_RANGE_FULLRANGE;
+ m_GlobalIspSettings.FocusSetting.VideoProc.Value.ul = 100;
+ break;
+ case KSCAMERA_EXTENDEDPROP_SCENEMODE_LANDSCAPE:
+ m_GlobalIspSettings.ISOMode = KSCAMERA_EXTENDEDPROP_ISO_AUTO;
+ m_GlobalIspSettings.EVCompensation.Value = 0;
+ m_GlobalIspSettings.EVCompensation.Mode = KSCAMERA_EXTENDEDPROP_EVCOMP_FULLSTEP;
+ m_GlobalIspSettings.WhiteBalanceSetting.VideoProc.Value.ul = WhiteBalanceDefault;
+ m_GlobalIspSettings.WhiteBalanceSetting.Mode = KSCAMERA_EXTENDEDPROP_WHITEBALANCE_TEMPERATURE;
+ m_GlobalIspSettings.WhiteBalanceMode = KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO;
+ m_GlobalIspSettings.ExposureMode = KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO;
+ m_GlobalIspSettings.ExposureSetting.VideoProc.Value.ul = DEF_EXPOSURE_TIME;
+ m_GlobalIspSettings.ExposureSetting.Mode = 0;
+ m_GlobalIspSettings.FocusMode = KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS | KSCAMERA_EXTENDEDPROP_FOCUS_RANGE_FULLRANGE;
+ m_GlobalIspSettings.FocusSetting.VideoProc.Value.ul = 100;
+ break;
+ case KSCAMERA_EXTENDEDPROP_SCENEMODE_NIGHTPORTRAIT:
+ m_GlobalIspSettings.ISOMode = KSCAMERA_EXTENDEDPROP_ISO_AUTO;
+ m_GlobalIspSettings.EVCompensation.Value = 0;
+ m_GlobalIspSettings.EVCompensation.Mode = KSCAMERA_EXTENDEDPROP_EVCOMP_FULLSTEP;
+ m_GlobalIspSettings.WhiteBalanceSetting.VideoProc.Value.ul = WhiteBalanceDefault;
+ m_GlobalIspSettings.WhiteBalanceSetting.Mode = KSCAMERA_EXTENDEDPROP_WHITEBALANCE_TEMPERATURE;
+ m_GlobalIspSettings.WhiteBalanceMode = KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO;
+ m_GlobalIspSettings.ExposureMode = KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO;
+ m_GlobalIspSettings.ExposureSetting.VideoProc.Value.ul = DEF_EXPOSURE_TIME;
+ m_GlobalIspSettings.ExposureSetting.Mode = 0;
+ m_GlobalIspSettings.FocusMode = KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS | KSCAMERA_EXTENDEDPROP_FOCUS_RANGE_FULLRANGE;
+ m_GlobalIspSettings.FocusSetting.VideoProc.Value.ul = 100;
+ break;
+ case KSCAMERA_EXTENDEDPROP_SCENEMODE_BACKLIT:
+ m_GlobalIspSettings.ISOMode = KSCAMERA_EXTENDEDPROP_ISO_AUTO;
+ m_GlobalIspSettings.EVCompensation.Value = 0;
+ m_GlobalIspSettings.EVCompensation.Mode = KSCAMERA_EXTENDEDPROP_EVCOMP_FULLSTEP;
+ m_GlobalIspSettings.WhiteBalanceSetting.VideoProc.Value.ul = WhiteBalanceDefault;
+ m_GlobalIspSettings.WhiteBalanceSetting.Mode = KSCAMERA_EXTENDEDPROP_WHITEBALANCE_TEMPERATURE;
+ m_GlobalIspSettings.WhiteBalanceMode = KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO;
+ m_GlobalIspSettings.ExposureMode = KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO;
+ m_GlobalIspSettings.ExposureSetting.VideoProc.Value.ul = DEF_EXPOSURE_TIME;
+ m_GlobalIspSettings.ExposureSetting.Mode = 0;
+ m_GlobalIspSettings.FocusMode = KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS | KSCAMERA_EXTENDEDPROP_FOCUS_RANGE_FULLRANGE;
+ m_GlobalIspSettings.FocusSetting.VideoProc.Value.ul = 100;
+ break;
+ default:
+ break;
+ }
+ DBG_TRACE("ExposureMode=0x%016llX, ExposureTime=%lld00ns",
+ m_GlobalIspSettings.ExposureMode, m_GlobalIspSettings.ExposureSetting.VideoProc.Value.ll);
+ return status;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_FOCUSPRIORITY
+NTSTATUS
+CSensorSimulation::
+GetFocusPriority(
+ _Inout_ CExtendedProperty *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ *pProperty = CExtendedProperty(m_GlobalIspSettings.FocusPriority);
+ DBG_TRACE("Is %s", m_GlobalIspSettings.FocusPriority ? "On" : "Off");
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_FOCUSPRIORITY
+NTSTATUS
+CSensorSimulation::
+SetFocusPriority(
+ _In_ CExtendedProperty *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ m_GlobalIspSettings.FocusPriority = pProperty->Flags;
+ return STATUS_SUCCESS;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_VIDEOHDR.
+NTSTATUS
+CSensorSimulation::
+GetVideoHDR(
+ _Inout_ CExtendedProperty *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ pProperty->Flags = m_VideoHDR;
+ pProperty->Capability = KSCAMERA_EXTENDEDPROP_VIDEOHDR_OFF |
+ KSCAMERA_EXTENDEDPROP_VIDEOHDR_ON |
+ KSCAMERA_EXTENDEDPROP_VIDEOHDR_AUTO;
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_VIDEOHDR.
+NTSTATUS
+CSensorSimulation::
+SetVideoHDR(
+ _In_ CExtendedProperty *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ m_VideoHDR = pProperty->Flags;
+ return STATUS_SUCCESS;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_VFR.
+NTSTATUS
+CSensorSimulation::
+GetVFR(
+ _Inout_ CExtendedProperty *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ pProperty->Flags = m_VFR;
+ pProperty->Capability = 0;
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_VFR.
+NTSTATUS
+CSensorSimulation::
+SetVFR(
+ _In_ CExtendedProperty *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ m_VFR = pProperty->Flags;
+ return STATUS_SUCCESS;
+}
+
+// KSPROPERTY_CAMERACONTROL_EXTENDED_ZOOM Get handler
+NTSTATUS
+CSensorSimulation::
+GetZoom(
+ _Inout_ CExtendedVidProcSetting *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ *pProperty = CExtendedVidProcSetting(m_ExtendedZoom);
+ pProperty->Capability = KSCAMERA_EXTENDEDPROP_ZOOM_DEFAULT |
+ KSCAMERA_EXTENDEDPROP_ZOOM_DIRECT |
+ KSCAMERA_EXTENDEDPROP_ZOOM_SMOOTH ;
+
+ // Update the zoom factor.
+ //
+ // I am using the same pFilter->m_Zoom value here just to keep the extended and legacy
+ // controls tied together. It is not necessary to implement both in a real driver.
+ // However the legacy control was implemented first in this simulation and leaving both
+ // in place might have some value. But supporting both adds the question of whether they
+ // should both present a consistent view of zoom or if they should just save and report
+ // the values set for their own respective properties.
+ //
+ // I have chosen to support a consistent view of the zoom factor between the extended and
+ // legacy controls. Given that the legacy control was implemented first, I have chosen
+ // to keep that storage and rescale the value set by the extended zoom to match the
+ // legacy settings.
+ //
+ // But to make the two controls more consistent, I have changed the reported Ocular Focal
+ // Length to 2^16, which matches the implied denominator in Q16 format - the format used
+ // by this extended property. So as long as lOcularFocalLength is 0x10000, the following
+ // function should not change the reported value at all. This should simplify any
+ // debugging or tracing.
+ //
+ DBG_TRACE("Legacy Zoom Value = %d", m_Zoom.Value);
+
+ // To ensure we clear out the high order value in the VideoProc
+ // union, we'll assign the LONG to LONGLONG field.
+ pProperty->m_Setting.VideoProc.Value.ll = (LONG) (TO_Q16(m_Zoom.Value) / m_FocalLength.lOcularFocalLength);
+
+ DBG_TRACE("Extended Zoom Value = %d", pProperty->GetLONG());
+
+ return STATUS_SUCCESS;
+}
+
+// KSPROPERTY_CAMERACONTROL_EXTENDED_ZOOM Set handler
+NTSTATUS
+CSensorSimulation::
+SetZoom(
+ _In_ CExtendedVidProcSetting *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+
+ LONG Zoom = pProperty->GetLONG();
+ DBG_TRACE("Extended Zoom Value = %d", Zoom);
+
+ m_ExtendedZoom = *pProperty;
+ DBG_TRACE("Zoom Flags = 0x%016llX", m_ExtendedZoom.Flags);
+
+ // Take us directly to the position if we're doing a direct zoom.
+ // Depends on IHVs, KSCAMERA_EXTENDEDPROP_ZOOM_DEFAULT may be either direct zoom or
+ // smooth zoom. Here direct zoom will be performed when DEFAULT is specified.
+ if( pProperty->Flags != KSCAMERA_EXTENDEDPROP_ZOOM_SMOOTH )
+ {
+ // Convert back to legacy notation...
+ //
+ // I am using the same pFilter->m_Zoom value here just to keep the extended and legacy
+ // controls tied together. It is not necessary to implement both in a real driver.
+ // However the legacy control was implemented first in this simulation and leaving both
+ // in place might have some value. But supporting both adds the question of whether they
+ // should both present a consistent view of zoom or if they should just save and report
+ // the values set for their own respective properties.
+ //
+ // I have chosen to support a consistent view of the zoom factor between the extended and
+ // legacy controls. Given that the legacy control was implemented first, I have chosen
+ // to keep that storage and rescale the value set by the extended zoom to match the
+ // legacy settings.
+ //
+ // But to make the two controls more consistent, I have changed the reported Ocular Focal
+ // Length to 2^16, which matches the implied denominator in Q16 format - the format used
+ // by this extended property. So as long as lOcularFocalLength is 0x10000, the following
+ // function should not change the reported value at all. This should simplify any
+ // debugging or tracing.
+ //
+ m_Zoom.Value = FROM_Q16(Zoom, m_FocalLength.lOcularFocalLength);
+ DBG_TRACE("Legacy Zoom Value = %d", m_Zoom.Value);
+ }
+
+ // It's always success; this is a sync control, so this isn't really used.
+ m_ExtendedZoom.Result = ntStatus;
+
+ DBG_LEAVE("()=0x%08X", ntStatus);
+ return ntStatus;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_VIDEOSTABILIZATION.
+NTSTATUS
+CSensorSimulation::
+GetVideoStabilization(
+ _Inout_ CExtendedProperty *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ pProperty->Flags = m_VideoStabilization;
+ pProperty->Capability = KSCAMERA_EXTENDEDPROP_VIDEOSTABILIZATION_OFF |
+ KSCAMERA_EXTENDEDPROP_VIDEOSTABILIZATION_ON |
+ KSCAMERA_EXTENDEDPROP_VIDEOSTABILIZATION_AUTO;
+
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_VIDEOSTABILIZATION.
+NTSTATUS
+CSensorSimulation::
+SetVideoStabilization(
+ _In_ CExtendedProperty *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ m_VideoStabilization = pProperty->Flags;
+ return STATUS_SUCCESS;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_OIS.
+NTSTATUS
+CSensorSimulation::
+GetOpticalImageStabilization(
+ _Inout_ CExtendedProperty *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ *pProperty = CExtendedProperty(m_OpticalImageStabilization);
+ pProperty->Capability = KSCAMERA_EXTENDEDPROP_OIS_OFF |
+ KSCAMERA_EXTENDEDPROP_OIS_ON |
+ KSCAMERA_EXTENDEDPROP_OIS_AUTO;
+
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_OIS.
+NTSTATUS
+CSensorSimulation::
+SetOpticalImageStabilization(
+ _In_ CExtendedProperty *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ m_OpticalImageStabilization = pProperty->Flags;
+ return STATUS_SUCCESS;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_ADVANCEDPHOTO.
+NTSTATUS
+CSensorSimulation::
+GetAdvancedPhoto(
+ _Inout_ CExtendedProperty *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ pProperty->Flags = m_AdvancedPhoto.Flags;
+ pProperty->Capability = m_AdvancedPhoto.Capability;
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_ADVANCEDPHOTO.
+NTSTATUS
+CSensorSimulation::
+SetAdvancedPhoto(
+ _In_ CExtendedProperty *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ m_AdvancedPhoto = *pProperty;
+ return STATUS_SUCCESS;
+}
+
+// Get [legacy] KSPROPERTY_CAMERACONTROL_FOCUS
+NTSTATUS
+CSensorSimulation::
+GetFocus(
+ _Inout_ PKSPROPERTY_CAMERACONTROL_S pKsCameraControl
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ pKsCameraControl->Capabilities = KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL |
+ KSPROPERTY_CAMERACONTROL_FLAGS_AUTO |
+ KSPROPERTY_CAMERACONTROL_FLAGS_ABSOLUTE;
+ pKsCameraControl->Flags = KSPROPERTY_CAMERACONTROL_FLAGS_ABSOLUTE;
+ // If we're currently set to AUTO or CONTINUOUS, report AUTO.
+ if (m_GlobalIspSettings.FocusMode &
+ ( KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO | KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS ))
+ {
+ pKsCameraControl->Flags |= KSPROPERTY_CAMERACONTROL_FLAGS_AUTO;
+ }
+ else if (m_GlobalIspSettings.FocusMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL)
+ {
+ pKsCameraControl->Flags |= KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL;
+ }
+ pKsCameraControl->Value = m_GlobalIspSettings.FocusSetting.VideoProc.Value.ul;
+
+ return STATUS_SUCCESS;
+}
+
+// Set [legacy] KSPROPERTY_CAMERACONTROL_FOCUS
+NTSTATUS
+CSensorSimulation::
+SetFocus(
+ _In_ PKSPROPERTY_CAMERACONTROL_S pKsCameraControl
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+
+ if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL)
+ {
+ // Convert relative values to absolute.
+ if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_RELATIVE)
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+
+ if (NT_SUCCESS(ntStatus))
+ {
+ // We report these changes in the next metadata payload.
+ m_GlobalIspSettings.FocusSetting.VideoProc.Value.ul = pKsCameraControl->Value;
+ m_GlobalIspSettings.FocusMode =
+ KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL;
+
+ m_FocusNotifier = nullptr;
+ m_FocusState = KSCAMERA_EXTENDEDPROP_FOCUSSTATE_SEARCHING;
+
+ // Fire a one-shot timer to transition the focus state.
+ m_FocusTimer->Set(
+ -330000LL, // 33ms
+ FocusConvergence,
+ this);
+ }
+
+ }
+ else if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_AUTO)
+ {
+ m_GlobalIspSettings.FocusMode = KSPROPERTY_CAMERACONTROL_FLAGS_AUTO | KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK;
+
+ m_FocusNotifier = nullptr;
+ m_FocusState = KSCAMERA_EXTENDEDPROP_FOCUSSTATE_SEARCHING;
+
+ // Fire a one-shot timer to transition the focus state.
+ m_FocusTimer->Set(
+ -4000000LL, // 400ms
+ FocusConvergence,
+ this );
+ }
+ else
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+
+ return ntStatus;
+}
+
+// Get [legacy] KSPROPERTY_CAMERACONTROL_EXPOSURE
+NTSTATUS
+CSensorSimulation::
+GetExposure(
+ _Inout_ PKSPROPERTY_CAMERACONTROL_S pKsCameraControl
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ pKsCameraControl->Capabilities = KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL |
+ KSPROPERTY_CAMERACONTROL_FLAGS_AUTO |
+ KSPROPERTY_CAMERACONTROL_FLAGS_ABSOLUTE;
+ pKsCameraControl->Flags = KSPROPERTY_CAMERACONTROL_FLAGS_ABSOLUTE;
+ if (m_GlobalIspSettings.ExposureMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO)
+ {
+ pKsCameraControl->Flags |= KSPROPERTY_CAMERACONTROL_FLAGS_AUTO;
+ }
+ else if (m_GlobalIspSettings.ExposureMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL)
+ {
+ pKsCameraControl->Flags |= KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL;
+ }
+
+ pKsCameraControl->Value = Exposure100nsToBinaryLog(m_GlobalIspSettings.ExposureSetting.VideoProc.Value.ll);
+
+ DBG_TRACE("ExposureValue=%d, ExposureMode=0x%016llX, ExposureTime=%lld00ns",
+ pKsCameraControl->Value, m_GlobalIspSettings.ExposureMode, m_GlobalIspSettings.ExposureSetting.VideoProc.Value.ll);
+
+ return STATUS_SUCCESS;
+}
+
+// Set [legacy] KSPROPERTY_CAMERACONTROL_EXPOSURE
+NTSTATUS
+CSensorSimulation::
+SetExposure(
+ _In_ PKSPROPERTY_CAMERACONTROL_S pKsCameraControl
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+ NTSTATUS ntStatus = BoundsCheckSigned( pKsCameraControl->Value, ExposureRangeAndStep[0] );
+
+ if( NT_SUCCESS(ntStatus) )
+ {
+ if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL)
+ {
+ // Convert relative values to absolute.
+ if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_RELATIVE || !ExposureBinaryLogIsValid(pKsCameraControl->Value))
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+
+ if (NT_SUCCESS(ntStatus))
+ {
+ // We report these changes in the next metadata payload
+ m_GlobalIspSettings.ExposureSetting.VideoProc.Value.ll = ExposureBinaryLogTo100ns(pKsCameraControl->Value);
+ m_GlobalIspSettings.ExposureMode =
+ KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL;
+ }
+ }
+ else if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_AUTO)
+ {
+ m_GlobalIspSettings.ExposureMode = KSPROPERTY_CAMERACONTROL_FLAGS_AUTO | KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK;
+
+ }
+ else
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+ }
+ DBG_TRACE("ExposureValue=%d, ExposureMode=0x%016llX, ExposureTime=%lld00ns",
+ pKsCameraControl->Value, m_GlobalIspSettings.ExposureMode, m_GlobalIspSettings.ExposureSetting.VideoProc.Value.ll);
+
+ return ntStatus;
+}
+
+// Update the zoom factor over time.
+void
+CSensorSimulation::
+SmoothZoom()
+{
+ PAGED_CODE();
+
+#define ZOOM_SPEED (LONG) (TO_Q16(1) * 0.07f)
+#define ZOOM_SPEED_VIDEO_RECORDING (LONG) (TO_Q16(1) * 0.02f)
+#define ZOOM_EPSILON (LONG)(TO_Q16(1) * 0.005f)
+
+ LONG currentZoom = (LONG)
+ (TO_Q16(m_Zoom.Value) /
+ m_FocalLength.lOcularFocalLength);
+ LONG targetZoom = m_ExtendedZoom.GetLONG();
+
+ LONG ZoomDelta = abs(currentZoom - targetZoom);
+
+ // Jump to target if we are very close
+ if( ZoomDelta <= ZOOM_EPSILON )
+ {
+ currentZoom = targetZoom;
+ }
+ else
+ {
+ // Zoom direction
+ bool bZoomIn = (targetZoom > currentZoom);
+ LONG OpModeZoomSpeed = ZOOM_SPEED;
+
+ // Use lower zoom speed for video, if any record pin is running.
+ for( ULONG VideoIndex=GetNextVideoIndex(); IsValidIndex(VideoIndex); VideoIndex=GetNextVideoIndex(VideoIndex) )
+ {
+ if( PinRunning == m_HardwareSimulation[VideoIndex]->GetState() )
+ {
+ OpModeZoomSpeed = ZOOM_SPEED_VIDEO_RECORDING;
+ }
+ }
+
+ // Calculate zoom step that is relative to current zoom factor.
+ // the bigger the current zoom factor the bigger the step.
+ LONG ZoomStep;
+ if( bZoomIn )
+ {
+ ZoomStep = MULT_Q16(OpModeZoomSpeed, currentZoom);
+ }
+ else
+ {
+ ZoomStep = currentZoom - DIV_Q16(currentZoom, (TO_Q16(1) + OpModeZoomSpeed));
+ }
+
+ if( ZoomDelta < 2 * ZoomStep)
+ {
+ // decrease step when close to target
+ ZoomStep = MULT_Q16(ZoomDelta, ((LONG)(TO_Q16(1) * 0.4f)));
+ }
+
+ if (bZoomIn)
+ {
+ currentZoom += ZoomStep;
+ }
+ else
+ {
+ currentZoom -= ZoomStep;
+ }
+ }
+
+ // Convert back to the zoom factor.
+ m_Zoom.Value = FROM_Q16(currentZoom, m_FocalLength.lOcularFocalLength);
+
+ if (!NT_SUCCESS(BoundsCheckSigned(m_Zoom.Value, ZoomRangeAndStep[0])))
+ {
+ m_Zoom.Value = FROM_Q16(targetZoom, m_FocalLength.lOcularFocalLength);
+ }
+
+ DBG_LEAVE(" m_Zoom.Value=%d, FocusMode=0x%016llX", m_Zoom.Value, m_GlobalIspSettings.FocusMode);
+}
+
+
+// Adjust the zoom for each preview frame if the zoom is in motion.
+// This function is used by both the legacy relative zoom control
+// and the extended property smooth zoom control.
+void
+CSensorSimulation::
+UpdateZoom(void)
+{
+ PAGED_CODE();
+
+ // Legacy zoom relative adjustment.
+ LONG Value = m_Zoom.Value + m_ZoomRelative.Value;
+
+ if (NT_SUCCESS(BoundsCheckSigned(Value, ZoomRangeAndStep[0])))
+ {
+ m_Zoom.Value = Value;
+ }
+ else
+ {
+ m_ZoomRelative.Value = 0;
+ }
+
+ // Extended property zoom / smooth zoom adjustment.
+ SmoothZoom();
+}
+
+// Get [legacy] KSPROPERTY_CAMERACONTROL_ZOOM
+NTSTATUS
+CSensorSimulation::
+GetZoom(
+ _Inout_ PKSPROPERTY_CAMERACONTROL_S pKsCameraControl
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ pKsCameraControl->Capabilities = m_Zoom.Capabilities;
+ pKsCameraControl->Flags = m_Zoom.Flags;
+ pKsCameraControl->Value = m_Zoom.Value;
+
+ return STATUS_SUCCESS;
+}
+
+// Set [legacy] KSPROPERTY_CAMERACONTROL_ZOOM
+NTSTATUS
+CSensorSimulation::
+SetZoom(
+ _In_ PKSPROPERTY_CAMERACONTROL_S pKsCameraControl
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+
+ if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL)
+ {
+ // Convert relative values to absolute.
+ if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_RELATIVE)
+ {
+ pKsCameraControl->Value += m_Zoom.Value;
+ }
+
+ // Bounds check
+ ntStatus = BoundsCheckSigned(pKsCameraControl->Value, ZoomRangeAndStep[0]);
+ if (NT_SUCCESS(ntStatus))
+ {
+ // We report these changes in the next metadata payload.
+ m_Zoom.Value = pKsCameraControl->Value;
+ m_Zoom.Flags =
+ KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL |
+ KSPROPERTY_CAMERACONTROL_FLAGS_ABSOLUTE;
+ }
+ }
+ else if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_AUTO)
+ {
+ m_Zoom.Flags = KSPROPERTY_CAMERACONTROL_FLAGS_AUTO;
+ }
+ else
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+
+ return ntStatus;
+}
+
+// Get [legacy] KSPROPERTY_CAMERACONTROL_ZOOM_RELATIVE
+NTSTATUS
+CSensorSimulation::
+GetZoomRelative(
+ _Inout_ PKSPROPERTY_CAMERACONTROL_S pKsCameraControl
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ pKsCameraControl->Capabilities = m_ZoomRelative.Capabilities;
+ pKsCameraControl->Flags = m_ZoomRelative.Flags;
+ pKsCameraControl->Value = m_ZoomRelative.Value;
+
+ return STATUS_SUCCESS;
+}
+
+// Set [legacy] KSPROPERTY_CAMERACONTROL_ZOOM_RELATIVE
+NTSTATUS
+CSensorSimulation::
+SetZoomRelative(
+ _In_ PKSPROPERTY_CAMERACONTROL_S pKsCameraControl
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+
+ if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL)
+ {
+ // Convert relative values to absolute.
+ if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_RELATIVE)
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+ else
+ {
+ // Bounds check
+ ntStatus = BoundsCheckSigned(pKsCameraControl->Value, ZoomRelativeRangeAndStep[0]);
+ }
+
+ if (NT_SUCCESS(ntStatus))
+ {
+ // We report these changes in the next metadata payload.
+ m_ZoomRelative.Value = pKsCameraControl->Value;
+ m_ZoomRelative.Flags =
+ KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL |
+ KSPROPERTY_CAMERACONTROL_FLAGS_ABSOLUTE;
+ }
+ }
+ else
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+
+ return ntStatus;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_PAN
+NTSTATUS
+CSensorSimulation::
+GetPan(
+ _Inout_ PKSPROPERTY_CAMERACONTROL_S pKsCameraControl
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ pKsCameraControl->Capabilities = m_Pan.Capabilities;
+ pKsCameraControl->Flags = m_Pan.Flags;
+ pKsCameraControl->Value = m_Pan.Value;
+
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_PAN
+NTSTATUS
+CSensorSimulation::
+SetPan(
+ _In_ PKSPROPERTY_CAMERACONTROL_S pKsCameraControl
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+
+ if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL)
+ {
+ // Convert relative values to absolute.
+ if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_RELATIVE)
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+
+ if (NT_SUCCESS(ntStatus))
+ {
+ // Bounds check
+ ntStatus = BoundsCheckSigned(pKsCameraControl->Value, PanRangeAndStep[0]);
+ if (NT_SUCCESS(ntStatus))
+ {
+ // We report these changes in the next metadata payload.
+ m_Pan.Value = pKsCameraControl->Value;
+ m_Pan.Flags =
+ KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL |
+ KSPROPERTY_CAMERACONTROL_FLAGS_ABSOLUTE;
+ }
+ }
+ }
+ else if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_AUTO)
+ {
+ m_Pan.Flags = KSPROPERTY_CAMERACONTROL_FLAGS_AUTO;
+ }
+ else
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+
+ return ntStatus;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_ROLL
+NTSTATUS
+CSensorSimulation::
+GetRoll(
+ _Inout_ PKSPROPERTY_CAMERACONTROL_S pKsCameraControl
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ pKsCameraControl->Capabilities = m_Roll.Capabilities;
+ pKsCameraControl->Flags = m_Roll.Flags;
+ pKsCameraControl->Value = m_Roll.Value;
+
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_ROLL
+NTSTATUS
+CSensorSimulation::
+SetRoll(
+ _In_ PKSPROPERTY_CAMERACONTROL_S pKsCameraControl
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+
+ if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL)
+ {
+ // Convert relative values to absolute.
+ if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_RELATIVE)
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+ if (NT_SUCCESS(ntStatus))
+ {
+ // Bounds check
+ ntStatus = BoundsCheckSigned(pKsCameraControl->Value, RollRangeAndStep[0]);
+ if (NT_SUCCESS(ntStatus))
+ {
+ // We report these changes in the next metadata payload.
+ m_Roll.Value = pKsCameraControl->Value;
+ m_Roll.Flags =
+ KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL |
+ KSPROPERTY_CAMERACONTROL_FLAGS_ABSOLUTE;
+ }
+ }
+ }
+ else if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_AUTO)
+ {
+ m_Roll.Flags = KSPROPERTY_CAMERACONTROL_FLAGS_AUTO;
+ }
+ else
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+
+ return ntStatus;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_TILT
+NTSTATUS
+CSensorSimulation::
+GetTilt(
+ _Inout_ PKSPROPERTY_CAMERACONTROL_S pKsCameraControl
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ pKsCameraControl->Capabilities = m_Tilt.Capabilities;
+ pKsCameraControl->Flags = m_Tilt.Flags;
+ pKsCameraControl->Value = m_Tilt.Value;
+
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_TILT
+NTSTATUS
+CSensorSimulation::
+SetTilt(
+ _In_ PKSPROPERTY_CAMERACONTROL_S pKsCameraControl
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+
+ if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL)
+ {
+ // Convert relative values to absolute.
+ if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_RELATIVE)
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+ if (NT_SUCCESS(ntStatus))
+ {
+ // Bounds check
+ ntStatus = BoundsCheckSigned(pKsCameraControl->Value, TiltRangeAndStep[0]);
+ if (NT_SUCCESS(ntStatus))
+ {
+ // We report these changes in the next metadata payload.
+ m_Tilt.Value = pKsCameraControl->Value;
+ m_Tilt.Flags =
+ KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL |
+ KSPROPERTY_CAMERACONTROL_FLAGS_ABSOLUTE;
+ }
+ }
+ }
+ else if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_AUTO)
+ {
+ m_Tilt.Flags = KSPROPERTY_CAMERACONTROL_FLAGS_AUTO;
+ }
+ else
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+
+ return ntStatus;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_FOCAL_LENGTH
+NTSTATUS
+CSensorSimulation::
+GetFocalLength(
+ _Inout_ PKSPROPERTY_CAMERACONTROL_FOCAL_LENGTH_S pKsCameraControl
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ pKsCameraControl->lOcularFocalLength = m_FocalLength.lOcularFocalLength;
+ pKsCameraControl->lObjectiveFocalLengthMax = m_FocalLength.lObjectiveFocalLengthMax;
+ pKsCameraControl->lObjectiveFocalLengthMin = m_FocalLength.lObjectiveFocalLengthMin;
+
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_FOCAL_LENGTH
+NTSTATUS
+CSensorSimulation::
+SetFocalLength(
+ _In_ PKSPROPERTY_CAMERACONTROL_FOCAL_LENGTH_S pKsCameraControl
+)
+{
+ PAGED_CODE();
+ return STATUS_NOT_FOUND;
+}
+
+// Get KSPROPERTY_VIDEOPROCAMP_BACKLIGHT_COMPENSATION
+NTSTATUS
+CSensorSimulation::
+GetBacklightCompensation(
+ _Inout_ PKSPROPERTY_VIDEOPROCAMP_S pKsCameraControl
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ pKsCameraControl->Capabilities = m_BacklightCompensation.Capabilities;
+ pKsCameraControl->Flags = m_BacklightCompensation.Flags;
+ pKsCameraControl->Value = m_BacklightCompensation.Value;
+
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_VIDEOPROCAMP_BACKLIGHT_COMPENSATION
+NTSTATUS
+CSensorSimulation::
+SetBacklightCompensation(
+ _In_ PKSPROPERTY_VIDEOPROCAMP_S pKsCameraControl
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+
+ if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL)
+ {
+ // Bounds check
+ ntStatus = BoundsCheckSigned(pKsCameraControl->Value, BacklightCompensationRangeAndStep[0]);
+ if (NT_SUCCESS(ntStatus))
+ {
+ // We report these changes in the next metadata payload.
+ m_BacklightCompensation.Value = pKsCameraControl->Value;
+ m_BacklightCompensation.Flags =
+ KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL;
+ }
+ }
+ else if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_AUTO)
+ {
+ m_BacklightCompensation.Flags = KSPROPERTY_CAMERACONTROL_FLAGS_AUTO;
+ }
+ else
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+
+ return ntStatus;
+}
+
+// Get KSPROPERTY_VIDEOPROCAMP_BRIGHTNESS
+NTSTATUS
+CSensorSimulation::
+GetBrightness(
+ _Inout_ PKSPROPERTY_VIDEOPROCAMP_S pKsCameraControl
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ pKsCameraControl->Capabilities = m_Brightness.Capabilities;
+ pKsCameraControl->Flags = m_Brightness.Flags;
+ pKsCameraControl->Value = m_Brightness.Value;
+
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_VIDEOPROCAMP_BRIGHTNESS
+NTSTATUS
+CSensorSimulation::
+SetBrightness(
+ _In_ PKSPROPERTY_VIDEOPROCAMP_S pKsCameraControl
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+
+ if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL)
+ {
+ // Bounds check
+ ntStatus = BoundsCheckSigned(pKsCameraControl->Value, BrightnessRangeAndStep[0]);
+ if (NT_SUCCESS(ntStatus))
+ {
+ // We report these changes in the next metadata payload.
+ m_Brightness.Value = pKsCameraControl->Value;
+ m_Brightness.Flags =
+ KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL;
+ }
+ }
+ else if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_AUTO)
+ {
+ m_Brightness.Flags = KSPROPERTY_CAMERACONTROL_FLAGS_AUTO;
+ }
+ else
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+
+ return ntStatus;
+}
+
+// Get KSPROPERTY_VIDEOPROCAMP_CONTRAST
+NTSTATUS
+CSensorSimulation::
+GetContrast(
+ _Inout_ PKSPROPERTY_VIDEOPROCAMP_S pKsCameraControl
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ pKsCameraControl->Capabilities = m_Contrast.Capabilities;
+ pKsCameraControl->Flags = m_Contrast.Flags;
+ pKsCameraControl->Value = m_Contrast.Value;
+
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_VIDEOPROCAMP_CONTRAST
+NTSTATUS
+CSensorSimulation::
+SetContrast(
+ _In_ PKSPROPERTY_VIDEOPROCAMP_S pKsCameraControl
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+
+ if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL)
+ {
+ // Bounds check
+ ntStatus = BoundsCheckSigned(pKsCameraControl->Value, ContrastRangeAndStep[0]);
+ if (NT_SUCCESS(ntStatus))
+ {
+ // We report these changes in the next metadata payload.
+ m_Contrast.Value = pKsCameraControl->Value;
+ m_Contrast.Flags =
+ KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL;
+ }
+ }
+ else if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_AUTO)
+ {
+ m_Contrast.Flags = KSPROPERTY_CAMERACONTROL_FLAGS_AUTO;
+ }
+ else
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+
+ return ntStatus;
+}
+
+// Get KSPROPERTY_VIDEOPROCAMP_HUE
+NTSTATUS
+CSensorSimulation::
+GetHue(
+ _Inout_ PKSPROPERTY_VIDEOPROCAMP_S pKsCameraControl
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ pKsCameraControl->Capabilities = m_Hue.Capabilities;
+ pKsCameraControl->Flags = m_Hue.Flags;
+ pKsCameraControl->Value = m_Hue.Value;
+
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_VIDEOPROCAMP_HUE
+NTSTATUS
+CSensorSimulation::
+SetHue(
+ _In_ PKSPROPERTY_VIDEOPROCAMP_S pKsCameraControl
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+
+ if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL)
+ {
+ // Bounds check
+ ntStatus = BoundsCheckSigned(pKsCameraControl->Value, HueRangeAndStep[0]);
+ if (NT_SUCCESS(ntStatus))
+ {
+ // We report these changes in the next metadata payload.
+ m_Hue.Value = pKsCameraControl->Value;
+ m_Hue.Flags =
+ KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL;
+ }
+ }
+ else if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_AUTO)
+ {
+ m_Hue.Flags = KSPROPERTY_CAMERACONTROL_FLAGS_AUTO;
+ }
+ else
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+
+ return ntStatus;
+}
+
+// Get KSPROPERTY_VIDEOPROCAMP_POWERLINE_FREQUENCY
+NTSTATUS
+CSensorSimulation::
+GetPowerlineFreq(
+ _Inout_ PKSPROPERTY_VIDEOPROCAMP_S pKsCameraControl
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ pKsCameraControl->Capabilities = m_PowerLineFreq.Capabilities;
+ pKsCameraControl->Flags = m_PowerLineFreq.Flags;
+ pKsCameraControl->Value = m_PowerLineFreq.Value;
+
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_VIDEOPROCAMP_POWERLINE_FREQUENCY
+NTSTATUS
+CSensorSimulation::
+SetPowerlineFreq(
+ _In_ PKSPROPERTY_VIDEOPROCAMP_S pKsCameraControl
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+
+ if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL)
+ {
+ // Bounds check
+ ntStatus = BoundsCheckSigned(pKsCameraControl->Value, PLFRangeAndStep[0]);
+ if (NT_SUCCESS(ntStatus))
+ {
+ // We report these changes in the next metadata payload.
+ m_PowerLineFreq.Value = pKsCameraControl->Value;
+ m_PowerLineFreq.Flags =
+ KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL;
+ }
+ }
+ else if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_AUTO)
+ {
+ m_PowerLineFreq.Flags = KSPROPERTY_CAMERACONTROL_FLAGS_AUTO;
+ m_PowerLineFreq.Value = POWERLINEFREQ_AUTO; // Auto is auto.
+ }
+ else
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+
+ return ntStatus;
+}
+
+// Get [legacy] KSPROPERTY_VIDEOPROCAMP_WHITEBALANCE
+NTSTATUS
+CSensorSimulation::
+GetWhiteBalance(
+ _Inout_ PKSPROPERTY_VIDEOPROCAMP_S pKsCameraControl
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+
+ pKsCameraControl->Capabilities = KSPROPERTY_CAMERACONTROL_FLAGS_AUTO | KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL;
+ if (m_GlobalIspSettings.WhiteBalanceMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO)
+ {
+ pKsCameraControl->Flags = KSPROPERTY_CAMERACONTROL_FLAGS_AUTO;
+ }
+ else
+ {
+ pKsCameraControl->Flags = KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL;
+ }
+
+ ULONG temperature = m_GlobalIspSettings.WhiteBalanceSetting.VideoProc.Value.ul;
+ if (m_GlobalIspSettings.WhiteBalanceSetting.Mode != KSCAMERA_EXTENDEDPROP_WHITEBALANCE_TEMPERATURE)
+ {
+ temperature = WhiteBalancePreset2Temperature(m_GlobalIspSettings.WhiteBalanceSetting.VideoProc.Value.ul);
+ }
+ pKsCameraControl->Value = (LONG)temperature;
+
+ return STATUS_SUCCESS;
+}
+
+// Set [legacy] KSPROPERTY_VIDEOPROCAMP_WHITEBALANCE
+NTSTATUS
+CSensorSimulation::
+SetWhiteBalance(
+ _In_ PKSPROPERTY_VIDEOPROCAMP_S pKsCameraControl
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock(m_SensorMutex);
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+
+ if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL)
+ {
+ // We report these changes in the next metadata payload.
+ m_GlobalIspSettings.WhiteBalanceSetting.VideoProc.Value.ul = pKsCameraControl->Value;
+ m_GlobalIspSettings.WhiteBalanceMode =
+ KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL;
+ m_GlobalIspSettings.WhiteBalanceSetting.Mode = KSCAMERA_EXTENDEDPROP_WHITEBALANCE_TEMPERATURE;
+ }
+ else if (pKsCameraControl->Flags & KSPROPERTY_CAMERACONTROL_FLAGS_AUTO)
+ {
+ m_GlobalIspSettings.WhiteBalanceMode =
+ KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO;
+ }
+ else
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ }
+
+ return ntStatus;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_HISTOGRAM.
+NTSTATUS
+CSensorSimulation::
+GetHistogram(
+ _Inout_ CExtendedProperty *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ pProperty->Flags = m_Histogram;
+ pProperty->m_Value.Value.ull = 0;
+ pProperty->Capability = 0;
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_HISTOGRAM.
+NTSTATUS
+CSensorSimulation::
+SetHistogram(
+ _In_ CExtendedProperty *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ m_Histogram = pProperty->Flags;
+
+ // Adjust the reported metadata buffer size for preview.
+ m_MetadataInfo[pProperty->PinId] =
+ CExtendedMetadata::METADATA_MAX +
+ (( m_Histogram == KSCAMERA_EXTENDEDPROP_HISTOGRAM_ON ) ? sizeof(CAMERA_METADATA_HISTOGRAM) : 0 ) ;
+
+ return STATUS_SUCCESS;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_METADATA
+NTSTATUS
+CSensorSimulation::
+GetMetadata(
+ _Inout_ CExtendedMetadata *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ *pProperty = m_MetadataInfo[pProperty->PinId];
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_METADATA
+NTSTATUS
+CSensorSimulation::
+SetMetadata(
+ _In_ CExtendedMetadata *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ *pProperty = m_MetadataInfo[pProperty->PinId];
+ return STATUS_SUCCESS;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_OPTIMIZATIONHINT
+NTSTATUS
+CSensorSimulation::
+GetOptimizationHint(
+ _Inout_ CExtendedProperty *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ *pProperty = m_OptimizationHint;
+ pProperty->Capability =
+ KSCAMERA_EXTENDEDPROP_OPTIMIZATION_PHOTO |
+ KSCAMERA_EXTENDEDPROP_OPTIMIZATION_VIDEO |
+ KSCAMERA_EXTENDEDPROP_OPTIMIZATION_QUALITY |
+ KSCAMERA_EXTENDEDPROP_OPTIMIZATION_LATENCY |
+ KSCAMERA_EXTENDEDPROP_OPTIMIZATION_POWER |
+ KSCAMERA_EXTENDEDPROP_OPTIMIZATION_DEFAULT;
+
+ DBG_TRACE( "Hint = 0x%016llX", m_OptimizationHint.Flags );
+
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_OPTIMIZATIONHINT
+NTSTATUS
+CSensorSimulation::
+SetOptimizationHint(
+ _In_ CExtendedProperty *pProperty
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ m_OptimizationHint = *pProperty;
+
+ DBG_TRACE( "Hint = 0x%016llX", m_OptimizationHint.Flags );
+
+ return STATUS_SUCCESS;
+}
+
+// Get for PROPSETID_VIDCAP_CAMERACONTROL_VIDEO_STABILIZATION:0
+NTSTATUS
+CSensorSimulation::
+GetVideoStabMode(
+ _Inout_ KSPROPERTY_CAMERACONTROL_VIDEOSTABILIZATION_MODE_S *pMode
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ pMode->Capabilities =
+ KSPROPERTY_CAMERACONTROL_VIDEOSTABILIZATION_MODE_FLAGS_AUTO |
+ KSPROPERTY_CAMERACONTROL_VIDEOSTABILIZATION_MODE_FLAGS_MANUAL ;
+ pMode->VideoStabilizationMode = m_VideoStabMode;
+ return STATUS_SUCCESS;
+}
+
+// Set for PROPSETID_VIDCAP_CAMERACONTROL_VIDEO_STABILIZATION:0
+NTSTATUS
+CSensorSimulation::
+SetVideoStabMode(
+ _In_ KSPROPERTY_CAMERACONTROL_VIDEOSTABILIZATION_MODE_S *pMode
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ m_VideoStabMode = pMode->VideoStabilizationMode;
+ return STATUS_SUCCESS;
+}
+
+// Get for KSPROPERTY_CAMERACONTROL_FLASH_PROPERTY_ID
+NTSTATUS
+CSensorSimulation::
+GetFlash(
+ _Inout_ KSPROPERTY_CAMERACONTROL_FLASH_S *pFlash
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ pFlash->Capabilities =
+ KSPROPERTY_CAMERACONTROL_FLASH_FLAGS_AUTO |
+ KSPROPERTY_CAMERACONTROL_FLASH_FLAGS_MANUAL ;
+ pFlash->Flash = m_Flash;
+ return STATUS_SUCCESS;
+}
+
+// Set for KSPROPERTY_CAMERACONTROL_FLASH_PROPERTY_ID
+NTSTATUS
+CSensorSimulation::
+SetFlash(
+ _In_ KSPROPERTY_CAMERACONTROL_FLASH_S *pFlash
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ m_Flash = pFlash->Flash;
+ return STATUS_SUCCESS;
+}
+
+// Get for KSPROPERTY_CAMERACONTROL_IMAGE_PIN_CAPABILITY_PROPERTY_ID
+NTSTATUS
+CSensorSimulation::
+GetPinDependence(
+ _Inout_ KSPROPERTY_CAMERACONTROL_IMAGE_PIN_CAPABILITY_S *pCaps
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ // Limit capabilities to the valid set.
+ pCaps->Capabilities &=
+ ( KSPROPERTY_CAMERACONTROL_IMAGE_PIN_CAPABILITY_EXCLUSIVE_WITH_RECORD |
+ KSPROPERTY_CAMERACONTROL_IMAGE_PIN_CAPABILITY_SEQUENCE_EXCLUSIVE_WITH_RECORD );
+
+ return STATUS_SUCCESS;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOTRIGGERTIME
+NTSTATUS
+CSensorSimulation::
+GetTriggerTime(
+ _Inout_ CExtendedProperty *pQPC
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ pQPC->Flags = 0;
+ NTSTATUS Status = GetQPC( pQPC->PinId, &pQPC->m_Value.Value.ull );
+
+ if( NT_SUCCESS(Status) )
+ {
+ pQPC->Flags = ( pQPC->m_Value.Value.ull != 0 ) ?
+ KSPROPERTY_CAMERA_PHOTOTRIGGERTIME_SET :
+ KSPROPERTY_CAMERA_PHOTOTRIGGERTIME_CLEAR;
+ }
+ return Status;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOTRIGGERTIME
+NTSTATUS
+CSensorSimulation::
+SetTriggerTime(
+ _In_ CExtendedProperty *pQPC
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ ULONGLONG Time = ( pQPC->Flags & KSPROPERTY_CAMERA_PHOTOTRIGGERTIME_SET ) ? *pQPC : 0;
+ return SetQPC( pQPC->PinId, Time );
+}
+
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_TORCHMODE
+NTSTATUS
+CSensorSimulation::
+GetTorchMode(
+ _Inout_ CExtendedProperty *pTorchMode
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ *pTorchMode = m_TorchMode;
+ pTorchMode->Capability =
+ KSCAMERA_EXTENDEDPROP_VIDEOTORCH_OFF |
+ KSCAMERA_EXTENDEDPROP_VIDEOTORCH_ON |
+ KSCAMERA_EXTENDEDPROP_VIDEOTORCH_ON_ADJUSTABLEPOWER;
+
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_TORCHMODE
+NTSTATUS
+CSensorSimulation::
+SetTorchMode(
+ _In_ CExtendedProperty *pTorchMode
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ m_TorchMode = *pTorchMode;
+ return STATUS_SUCCESS;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOMODE
+NTSTATUS
+CSensorSimulation::
+GetPhotoMode(
+ _Inout_ CExtendedPhotoMode *pPhotoMode
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ pPhotoMode->Flags = m_PhotoMode.Flags;
+ pPhotoMode->Capability = KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL | KSCAMERA_EXTENDEDPROP_PHOTOMODE_SEQUENCE;
+ pPhotoMode->MaxHistoryFrames() = IMAGE_CAPTURE_PIN_MAXIMUM_HISTORY_FRAMES;
+ pPhotoMode->RequestedHistoryFrames() = m_PhotoMode.RequestedHistoryFrames();
+ pPhotoMode->SubMode() = m_PhotoMode.SubMode();
+
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOMODE
+NTSTATUS
+CSensorSimulation::
+SetPhotoModeAsync(
+ _In_ CExtendedPhotoMode *pPhotoMode,
+ _In_ CNotifier *Notifier // Use to notify the framework that the control is done.
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ DBG_ENTER("()");
+
+ m_PhotoMode = *pPhotoMode;
+
+ NTSTATUS Status =
+ SetPinMode( pPhotoMode->PinId, pPhotoMode->Flags, pPhotoMode->RequestedHistoryFrames() );
+
+ // Tell the caller that we're done.
+ Notifier->Set();
+
+ DBG_LEAVE("()=0x%08X",Status);
+ return Status;
+}
+
+/*
+ * KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOMAXFRAMERATE Get Handler
+ */
+NTSTATUS
+CSensorSimulation::
+GetPhotoMaxFrameRate(
+ _Inout_ CExtendedProperty *pPhotoMaxFrameRate
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ pPhotoMaxFrameRate->Flags = m_MaxFrameRate.Flags;
+ pPhotoMaxFrameRate->m_Value = m_MaxFrameRate.m_Value;
+ // If max frame rate is 0,0, we want to indicate 30fps to the caller.
+ if ((*pPhotoMaxFrameRate).m_Value.Value.ull == 0)
+ {
+ (*pPhotoMaxFrameRate).m_Value.Value.ratio.HighPart = 30000;
+ (*pPhotoMaxFrameRate).m_Value.Value.ratio.LowPart = 1000;
+ }
+ pPhotoMaxFrameRate->Capability = KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL;
+ return STATUS_SUCCESS;
+}
+
+/*
+ * KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOMAXFRAMERATE Set Handler
+ */
+NTSTATUS
+CSensorSimulation::
+SetPhotoMaxFrameRateAsync(
+ _In_ CExtendedProperty *pPhotoMaxFrameRate,
+ _In_ CNotifier *Notifier // Use to notify the framework that the control is done.
+)
+{
+ PAGED_CODE();
+
+ ULONGLONG TimePerFrame = 0;
+ {
+ // Note: Don't lock around SetPhotoFrameRate() to avoid a priority inversion.
+ KScopedMutex lock( m_SensorMutex );
+
+ m_MaxFrameRate = *pPhotoMaxFrameRate;
+
+ // Try to apply the setting immediately.
+ LARGE_INTEGER PerformanceTime = { m_MaxFrameRate.m_Value.Value.ratio.LowPart };
+ LONGLONG Frequency = m_MaxFrameRate.m_Value.Value.ratio.HighPart;
+
+ if( Frequency != 0 )
+ {
+ TimePerFrame = KSCONVERT_PERFORMANCE_TIME( Frequency, PerformanceTime );
+ }
+ }
+
+ DBG_TRACE( "SetPhotoFrameRate(%lld)", TimePerFrame );
+
+ // Consume any error; we'll set the rate again when the pin starts.
+ SetPhotoFrameRate( pPhotoMaxFrameRate->PinId, TimePerFrame );
+
+ // Tell the caller that we're done.
+ Notifier->Set();
+
+ return STATUS_SUCCESS;
+}
+
+/*
+ * KSPROPERTY_CAMERACONTROL_EXTENDED_WARMSTART
+ */
+NTSTATUS
+CSensorSimulation::
+GetWarmStart(
+ _Inout_ CExtendedProperty *pWarmStart
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ *pWarmStart = m_WarmStartEnabled[pWarmStart->PinId];
+ pWarmStart->Capability =
+ KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL |
+ KSCAMERA_EXTENDEDPROP_WARMSTART_MODE_DISABLED |
+ KSCAMERA_EXTENDEDPROP_WARMSTART_MODE_ENABLED ;
+ return STATUS_SUCCESS;
+}
+
+/*
+ * KSPROPERTY_CAMERACONTROL_EXTENDED_WARMSTART
+ */
+NTSTATUS
+CSensorSimulation::
+SetWarmStartAsync(
+ _In_ CExtendedProperty *pWarmStart,
+ _In_ CNotifier *Notifier // Use to notify the framework that the control is done.
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ m_WarmStartEnabled[pWarmStart->PinId] = *pWarmStart;
+
+ // Tell the caller that we're done.
+ Notifier->Set();
+
+ return STATUS_SUCCESS;
+}
+
+/*
+ * KSPROPERTY_CAMERACONTROL_EXTENDED_MAXVIDFPS_PHOTORES Get Handler
+ */
+NTSTATUS
+CSensorSimulation::
+GetMaxVideoFpsForPhotoRes(
+ _Inout_ CExtendedMaxVideoFpsForPhotoRes *pPhotoRes
+)
+{
+ PAGED_CODE();
+
+ // We're just a simulation and have no constraints - set 30FPS.
+ pPhotoRes->PreviewFPSNum() =30;
+ pPhotoRes->PreviewFPSDenom() = 1;
+ pPhotoRes->CaptureFPSNum() = 30;
+ pPhotoRes->CaptureFPSDenom() = 1;
+
+ return STATUS_SUCCESS;
+}
+
+/*
+ * KSPROPERTY_CAMERACONTROL_EXTENDED_MAXVIDFPS_PHOTORES Set Handler
+ */
+NTSTATUS
+CSensorSimulation::
+SetMaxVideoFpsForPhotoRes(
+ _In_ CExtendedMaxVideoFpsForPhotoRes *pPhotoRes
+)
+{
+ PAGED_CODE();
+
+ // We don't really use this call.
+ return STATUS_SUCCESS;
+}
+
+// Get KSPROPERTY_CAMERACONTROL_EXTENDED_FIELDOFVIEW
+NTSTATUS
+CSensorSimulation::
+GetFieldOfView(
+ _Inout_ CExtendedFieldOfView *pFieldOfView
+)
+{
+ PAGED_CODE();
+
+ // Report dummy values.
+ *pFieldOfView = CExtendedFieldOfView();
+ pFieldOfView->NormalizedFocalLengthX() = 35;
+ pFieldOfView->NormalizedFocalLengthY() = 35;
+
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_CAMERACONTROL_EXTENDED_FIELDOFVIEW
+NTSTATUS
+CSensorSimulation::
+GetCameraAngleOffset(
+ _Inout_ CExtendedCameraAngleOffset *pAngle
+)
+{
+ PAGED_CODE();
+
+ // Just return zeros. We're dead-on, no tilt.
+ *pAngle = CExtendedCameraAngleOffset();
+
+ return STATUS_SUCCESS;
+}
+
+// KSPROPERTY_CAMERACONTROL_EXTENDED_ROI_CONFIGCAPS Get handler
+NTSTATUS
+CSensorSimulation::
+GetRoiConfigCaps(
+ _Inout_ CRoiConfig *pCaps
+)
+{
+ PAGED_CODE();
+ // No state accessed...
+ //KScopedMutex lock( m_SensorMutex );
+
+ // Our CRoiConfig ctor defines our capabilities.
+ *pCaps = CRoiConfig();
+
+ return STATUS_SUCCESS;
+}
+
+// Per Frame Settings Caps
+struct SOC_PFS_CAPS
+{
+ KSCAMERA_PERFRAMESETTING_CAP_HEADER Hdr;
+ SOC_CAP_WITH_STEPPING_LONGLONG ExposureTime;
+ KSCAMERA_PERFRAMESETTING_CAP_ITEM_HEADER Flash;
+ SOC_CAP_WITH_STEPPING EVCompensation;
+ SOC_CAP_WITH_STEPPING Iso;
+ SOC_CAP_WITH_STEPPING Focus;
+ KSCAMERA_PERFRAMESETTING_CAP_ITEM_HEADER StillConfirmation;
+} ;
+
+const ULONG SOC_PFS_NUMCAPS = 6;
+
+// Our predefined Variable Photo Sequence capabilities.
+SOC_PFS_CAPS g_PFSCaps =
+{
+ // KSCAMERA_PERFRAMESETTING_CAP_HEADER
+ { sizeof(SOC_PFS_CAPS), SOC_PFS_NUMCAPS, 0 }, //Hdr
+ // ExposureTime
+ {
+ // SOC_CAP_WITH_STEPPING_LONGLONG
+ {
+ // KSCAMERA_PERFRAMESETTING_CAP_ITEM_HEADER
+ sizeof(g_PFSCaps.ExposureTime), //Size
+ KSCAMERA_PERFRAMESETTING_ITEM_EXPOSURE_TIME, //Type
+ KSCAMERA_PERFRAMESETTING_AUTO //Flags
+ | KSCAMERA_PERFRAMESETTING_MANUAL
+ },
+ {
+ // KSPROPERTY_STEPPING_LONGLONG
+ 1000, //SteppingDelta (in us)
+ {
+ // KSPROPERTY_BOUNDS_LONGLONG
+ MIN_EXPOSURE_TIME, //SignedMinimum
+ MAX_EXPOSURE_TIME //SignedMaximum (arbitrary - 1 hour)
+ }
+ }
+ },
+ // Flash
+ {
+ // KSCAMERA_PERFRAMESETTING_CAP_ITEM_HEADER
+ sizeof(g_PFSCaps.Flash),
+ KSCAMERA_PERFRAMESETTING_ITEM_FLASH,
+ KSCAMERA_EXTENDEDPROP_FLASH_OFF
+ | KSCAMERA_EXTENDEDPROP_FLASH_ON
+ | KSCAMERA_EXTENDEDPROP_FLASH_ON_ADJUSTABLEPOWER
+ | KSCAMERA_EXTENDEDPROP_FLASH_AUTO
+ | KSCAMERA_EXTENDEDPROP_FLASH_AUTO_ADJUSTABLEPOWER
+ | KSCAMERA_EXTENDEDPROP_FLASH_REDEYEREDUCTION
+ },
+ // ExposureCompensation
+ {
+ // SOC_CAP_WITH_STEPPING
+ {
+ // KSCAMERA_PERFRAMESETTING_CAP_ITEM_HEADER
+ sizeof(g_PFSCaps.EVCompensation), //Size
+ KSCAMERA_PERFRAMESETTING_ITEM_EXPOSURE_COMPENSATION, //Type
+ KSCAMERA_PERFRAMESETTING_AUTO //Flags
+ | KSCAMERA_EXTENDEDPROP_EVCOMP_SIXTHSTEP
+ | KSCAMERA_EXTENDEDPROP_EVCOMP_QUARTERSTEP
+ | KSCAMERA_EXTENDEDPROP_EVCOMP_THIRDSTEP
+ | KSCAMERA_EXTENDEDPROP_EVCOMP_HALFSTEP
+ | KSCAMERA_EXTENDEDPROP_EVCOMP_FULLSTEP
+ },
+ {
+ // KSPROPERTY_STEPPING_LONG
+ 1, //SteppingDelta
+ 0, //Reserved
+ {
+ // KSPROPERTY_BOUNDS_LONG
+ -2, //SignedMinimum
+ 2 //SignedMaximum
+ }
+ }
+ },
+ // Iso
+ {
+ // SOC_CAP_WITH_STEPPING
+ {
+ // KSCAMERA_PERFRAMESETTING_CAP_ITEM_HEADER
+ sizeof(g_PFSCaps.Iso),
+ KSCAMERA_PERFRAMESETTING_ITEM_ISO,
+ KSCAMERA_EXTENDEDPROP_ISO_AUTO
+ | KSCAMERA_EXTENDEDPROP_ISO_MANUAL
+ },
+ {
+ // KSPROPERTY_STEPPING_LONG
+ 50, //SteppingDelta
+ 0, //Reserved
+ {
+ // KSPROPERTY_BOUNDS_LONG
+ 50, //SignedMinimum
+ 256000 //SignedMaximum
+ }
+ }
+ },
+ // Focus
+ {
+ // SOC_CAP_WITH_STEPPING
+ {
+ // KSCAMERA_PERFRAMESETTING_CAP_ITEM_HEADER
+ sizeof(g_PFSCaps.Focus), //Size
+ KSCAMERA_PERFRAMESETTING_ITEM_FOCUS, //Type
+ KSCAMERA_PERFRAMESETTING_AUTO //Flags
+ | KSCAMERA_PERFRAMESETTING_MANUAL
+ },
+ {
+ // KSPROPERTY_STEPPING_LONG
+ 10, //SteppingDelta (We'll use centimeters for kicks)
+ 0, //Reserved
+ {
+ // KSPROPERTY_BOUNDS_LONG
+ 0, //SignedMinimum
+ 10000 //SignedMaximum (100 meters max)
+ }
+ }
+ },
+ // StillConfirmation
+ {
+ // KSCAMERA_PERFRAMESETTING_CAP_ITEM_HEADER
+ sizeof(g_PFSCaps.StillConfirmation),
+ KSCAMERA_PERFRAMESETTING_ITEM_PHOTOCONFIRMATION,
+ 0
+ },
+};
+
+// Get KSPROPERTY_CAMERACONTROL_PERFRAMESETTING_CAPABILITY
+_Success_(return == 0)
+NTSTATUS
+CSensorSimulation::
+GetPfsCaps(
+ _Inout_opt_ KSCAMERA_PERFRAMESETTING_CAP_HEADER *Caps,
+ _Inout_ ULONG *Size
+)
+{
+ PAGED_CODE();
+
+ if( Caps )
+ {
+ size_t Length = sizeof(g_PFSCaps);
+ if( Size && *Size < Length )
+ {
+ Length = *Size;
+ }
+ RtlCopyMemory( Caps, &g_PFSCaps, Length );
+ }
+
+ *Size = sizeof(g_PFSCaps);
+
+ return STATUS_SUCCESS;
+}
+
+// KSPROPERTY_CAMERACONTROL_EXTENDED_ROI_ISPCONTROL Get handler
+NTSTATUS
+CSensorSimulation::
+GetRoi(
+ _Inout_ CRoiProperty *pRoi
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ // *pRoiProperty = ...
+ *pRoi = CRoiProperty(); // initialize it.
+
+ // Add control properties to it.
+ pRoi->Add( &m_RoiWhiteBalance ) ;
+ pRoi->Add( &m_RoiExposureMode ) ;
+ pRoi->Add( &m_RoiFocusMode ) ;
+
+ // Log what we created.
+ pRoi->Log();
+
+ return STATUS_SUCCESS;
+}
+
+// KSPROPERTY_CAMERACONTROL_EXTENDED_ROI_ISPCONTROL Set handler
+NTSTATUS
+CSensorSimulation::
+SetRoiAsync(
+ _In_ CRoiProperty *pRoi,
+ _In_ CNotifier *Notifier
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ if( pRoi->GetControlCount() == 0 )
+ {
+ // Clear all settings.
+ DBG_TRACE("Clearing all settings...");
+ m_RoiWhiteBalance = CWhiteBalanceRoiIspControl();
+ m_RoiExposureMode = CExposureRoiIspControl();
+ m_RoiFocusMode = CFocusRoiIspControl();
+ }
+ else
+ {
+ // Parse our settings.
+ DBG_TRACE("Parsing new settings...");
+ if( m_RoiWhiteBalance.
+ Init( pRoi, KSPROPERTY_CAMERACONTROL_EXTENDED_WHITEBALANCEMODE ) )
+ {
+ m_GlobalIspSettings.WhiteBalanceMode = m_RoiWhiteBalance.GetFlags();
+ m_RoiWhiteBalance.Log();
+ }
+ if( m_RoiExposureMode.
+ Init( pRoi, KSPROPERTY_CAMERACONTROL_EXTENDED_EXPOSUREMODE ) )
+ {
+ m_GlobalIspSettings.ExposureMode = m_RoiExposureMode.GetFlags();
+ m_RoiExposureMode.Log();
+ }
+ if( m_RoiFocusMode.
+ Init( pRoi, KSPROPERTY_CAMERACONTROL_EXTENDED_FOCUSMODE ) )
+ {
+ ULONGLONG Flags = m_RoiFocusMode.GetFlags();
+ DBG_TRACE("Requesting FocusMode = 0x%016llX", Flags);
+
+ if( Flags )
+ {
+ // If we've been asked to unlock, remove any lock flags.
+ if( Flags & KSCAMERA_EXTENDEDPROP_FOCUS_UNLOCK )
+ {
+ // Change our operation so we go back to the previous state.
+ Flags = m_GlobalIspSettings.FocusMode &
+ ~( KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK |
+ KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUSLOCK );
+ }
+
+ // Handle the stand-alone lock case by setting the appropriate flags.
+ if( ( Flags &
+ (KSCAMERA_EXTENDEDPROP_FOCUS_MODE_MASK |
+ KSCAMERA_EXTENDEDPROP_FOCUS_MODE_ADVANCED_MASK) ) ==
+ KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK )
+ {
+ if( m_GlobalIspSettings.FocusMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO )
+ {
+ Flags =
+ m_GlobalIspSettings.FocusMode | KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK;
+ }
+ if( m_GlobalIspSettings.FocusMode & KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS )
+ {
+ Flags =
+ m_GlobalIspSettings.FocusMode |= KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUSLOCK;
+ }
+ }
+ // Note: We do not simulate deferred completion.
+ m_FocusState = KSCAMERA_EXTENDEDPROP_FOCUSSTATE_FOCUSED;
+
+ // Record the Focus mode.
+ DBG_TRACE("Recording FocusMode = 0x%016llX", Flags);
+ m_GlobalIspSettings.FocusMode = Flags;
+ }
+
+ m_RoiFocusMode.Log();
+ }
+ }
+
+ Notifier->Set();
+ return STATUS_SUCCESS;
+}
+
+// KSPROPERTY_CAMERACONTROL_EXTENDED_ROI_ISPCONTROL size handler
+ULONG
+CSensorSimulation::
+SizeOfRoi()
+{
+ PAGED_CODE();
+
+ return
+ sizeof( CRoiProperty ) +
+ m_RoiWhiteBalance.GetSize() +
+ m_RoiExposureMode.GetSize() +
+ m_RoiFocusMode.GetSize() ;
+}
+
+
+// Get KSPROPERTY_VIDEOCONTROL_MODE.
+NTSTATUS
+CSensorSimulation::
+GetVideoControlMode(
+ _Inout_ KSPROPERTY_VIDEOCONTROL_MODE_S *pMode
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ pMode->Mode = GetTriggerMode(pMode->StreamIndex);
+
+ return STATUS_SUCCESS;
+}
+
+// Set KSPROPERTY_VIDEOCONTROL_MODE.
+NTSTATUS
+CSensorSimulation::
+SetVideoControlMode(
+ _In_ KSPROPERTY_VIDEOCONTROL_MODE_S *pMode
+)
+{
+ PAGED_CODE();
+
+ // Note: Trigger will acquire a lock on the hwsim.
+ return Trigger( pMode->StreamIndex, pMode->Mode );
+}
+
+// Get KSPROPERTY_VIDEOCONTROL_CAPS.
+NTSTATUS
+CSensorSimulation::
+GetVideoControlCaps(
+ _Inout_ KSPROPERTY_VIDEOCONTROL_CAPS_S *pCaps
+)
+{
+ PAGED_CODE();
+ KScopedMutex lock( m_SensorMutex );
+
+ pCaps->VideoControlCaps = 0;
+ if( IsStillIndex( pCaps->StreamIndex ) )
+ {
+ pCaps->VideoControlCaps =
+ KS_VideoControlFlag_IndependentImagePin |
+ KS_VideoControlFlag_Trigger |
+ KS_VideoControlFlag_StartPhotoSequenceCapture |
+ KS_VideoControlFlag_StopPhotoSequenceCapture;
+ }
+
+ return STATUS_SUCCESS;
+}
+