diff options
Diffstat (limited to 'AVStream/avscamera/sys/filter.cpp')
| -rw-r--r-- | AVStream/avscamera/sys/filter.cpp | 4080 |
1 files changed, 4080 insertions, 0 deletions
diff --git a/AVStream/avscamera/sys/filter.cpp b/AVStream/avscamera/sys/filter.cpp new file mode 100644 index 00000000..cb28775e --- /dev/null +++ b/AVStream/avscamera/sys/filter.cpp @@ -0,0 +1,4080 @@ +/************************************************************************** + + A/V Stream Camera Sample + + Copyright (c) 2001, Microsoft Corporation. + + File: + + filter.cpp + + Abstract: + + This file contains the filter level implementation for the base capture + filter class. It provides a wrapper on KSFILTER. + + CCaptureFilter holds state information for the filter and contains + implementations for standard camera controls. These implementations + validate arguments and capabilities of the control according to DDI + definitions. Once validated, control is passes to a CSensor object + to manipulate the state of camera. + + To add a new control, derive from CCaptureFilter and use one of the + DECLARE_PROPERTY_XXX() macros below to declare the property handlers. + You can also use the DEFINE_PROP_ITEM_XXX() and DEFINE_STD_EVENT_ITEM() + macros as aids in constructing a filter's automation table. + + History: + + created 3/12/2001 + +**************************************************************************/ + +#include "Common.h" + +/************************************************************************** + + PAGEABLE CODE + +**************************************************************************/ + +#ifdef ALLOC_PRAGMA +#pragma code_seg("PAGE") +#endif // ALLOC_PRAGMA + +CCaptureFilter::CCaptureFilter ( + _In_ PKSFILTER Filter +): +/*++ + +Routine Description: + + CCaptureFilter object construction. + +Arguments: + + Filter - + The AVStream filter being wrapped. + +Return Value: + + None + +--*/ + m_pCaptureDevice(NULL), + m_pPerFrameSettings(nullptr), + m_pinArray(nullptr), + m_PhotoModeNotifier( Filter, &KSEVENTSETID_ExtendedCameraControl, KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOMODE ), + m_PhotoMaxFrameRateNotifier( Filter, &KSEVENTSETID_ExtendedCameraControl, KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOMAXFRAMERATE) , + m_FocusNotifier( Filter, &KSEVENTSETID_ExtendedCameraControl, KSPROPERTY_CAMERACONTROL_EXTENDED_FOCUSMODE ), + m_FocusRectNotifier( Filter, &EVENTSETID_VIDCAP_CAMERACONTROL_REGION_OF_INTEREST, KSPROPERTY_CAMERACONTROL_REGION_OF_INTEREST_PROPERTY_ID ), + m_IsoNotifier( Filter, &KSEVENTSETID_ExtendedCameraControl, KSPROPERTY_CAMERACONTROL_EXTENDED_ISO ), + m_IsoAdvancedNotifier( Filter, &KSEVENTSETID_ExtendedCameraControl, KSPROPERTY_CAMERACONTROL_EXTENDED_ISO_ADVANCED ), + m_EvCompensationNotifier( Filter, &KSEVENTSETID_ExtendedCameraControl, KSPROPERTY_CAMERACONTROL_EXTENDED_EVCOMPENSATION ), + m_WhiteBalanceNotifier( Filter, &KSEVENTSETID_ExtendedCameraControl, KSPROPERTY_CAMERACONTROL_EXTENDED_WHITEBALANCEMODE ), + m_ExposureNotifier( Filter, &KSEVENTSETID_ExtendedCameraControl, KSPROPERTY_CAMERACONTROL_EXTENDED_EXPOSUREMODE ), + m_SceneModeNotifier( Filter, &KSEVENTSETID_ExtendedCameraControl, KSPROPERTY_CAMERACONTROL_EXTENDED_SCENEMODE ), + m_ThumbnailNotifier( Filter, &KSEVENTSETID_ExtendedCameraControl, KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOTHUMBNAIL ), + m_WarmStartNotifier( Filter, &KSEVENTSETID_ExtendedCameraControl, KSPROPERTY_CAMERACONTROL_EXTENDED_WARMSTART ), + m_RoiNotifier( Filter, &KSEVENTSETID_ExtendedCameraControl, KSPROPERTY_CAMERACONTROL_EXTENDED_ROI_ISPCONTROL ), + m_ProfileNotifier( Filter, &KSEVENTSETID_ExtendedCameraControl, KSPROPERTY_CAMERACONTROL_EXTENDED_PROFILE ) +{ + + PAGED_CODE(); + + DBG_ENTER("(Filter=%p)", Filter); + + m_pKSFilter = Filter; + + m_pCaptureDevice = CCaptureDevice::Recast(KsFilterGetDevice(Filter)); + + KeQuerySystemTime (&m_StartTime); + + m_Profile.ProfileId = KSCAMERAPROFILE_Legacy; + m_Profile.Index = 0; + m_Profile.Reserved = 0; + + DBG_ENTER("(Filter=%p)", Filter); +} + +NTSTATUS +CCaptureFilter:: +Initialize() +/*++ + +Routine Description: + + Post construction initialization. + +Arguments: + + [None] + +Return Value: + + Success / failure + +--*/ +{ + + PAGED_CODE(); + + NTSTATUS Status = STATUS_SUCCESS; + + DBG_ENTER("(Filter=%S)", GetFilterName()); + + // Get Sensor object from our parent device object. + + m_Sensor = m_pCaptureDevice->GetSensor(m_pKSFilter); + NT_ASSERT(m_Sensor); + + // We get a nullptr back if the Filter doesn't match one of our's. + if( !m_Sensor ) + { + Status = STATUS_INVALID_PARAMETER; + goto done; + } + + // In reality we're just adding a reference to the sensor for this filter. + // The sensor has no back pointer to the filter since more than one filter + // can be open at a time. + IFFAILED_EXIT( m_Sensor->AddFilter(m_pKSFilter) ); + + IFNULL_EXIT(m_pinArray = new (PagedPool, 'sniP') CCapturePin *[m_Sensor->GetPinCount()]); + + for( ULONG i=0; i<m_Sensor->GetPinCount(); i++ ) + { + m_pinArray[i] = nullptr; + } + +done: + DBG_LEAVE("(Filter=%S)=0x%08X", GetFilterName(), Status); + return Status; +} + +void +CCaptureFilter::Cleanup() +/*++ + +Routine Description: + + Clean up. Cancels any outstanding operations on the sensor. + +Arguments: + + [None] + +Return Value: + + [None] + +--*/ +{ + PAGED_CODE(); + + // Cancel all Async operations. Ignore any failures. + m_Sensor->CancelPhotoMode(); + m_Sensor->CancelPhotoMaxFrameRate(); + m_Sensor->CancelFocus(); + m_Sensor->CancelFocusRect(); + m_Sensor->CancelIso(); + m_Sensor->CancelIsoAdvanced(); + m_Sensor->CancelEvCompensation(); + m_Sensor->CancelWhiteBalance(); + m_Sensor->CancelExposure(); + m_Sensor->CancelSceneMode(); + m_Sensor->CancelThumbnail(); + m_Sensor->CancelWarmStart(); + m_Sensor->CancelRoi(); +} + +// +// ~CCaptureFilter(): +// +// The capture filter destructor. +// +CCaptureFilter::~CCaptureFilter() +{ + PAGED_CODE(); + + LPCWSTR Name = GetFilterName(); + DBG_ENTER("(%S)", Name); + + delete [] ((PBYTE) m_pPerFrameSettings); + + // In reality we're just removing a reference to the sensor for this filter. + m_Sensor->RemoveFilter(m_pKSFilter); + + // The sensor may need to do some cleanup. In particular, the image pin + // may need to have some things reset. + m_Sensor->Reset(); + + delete [] m_pinArray; + + DBG_LEAVE("(%S)", Name); +} + + +NTSTATUS +CCaptureFilter:: +DispatchCreate ( + _In_ PKSFILTER Filter, + _In_ PIRP Irp +) +/*++ + +Routine Description: + + Static function for creation dispatch for the capture filter. It creates + the CCaptureFilter object. + +Arguments: + + Filter - + The AVStream filter being created + + Irp - + The creation Irp + +Return Value: + + Success / failure + +--*/ + +{ + PAGED_CODE(); + + DBG_ENTER("(Filter=0x%p)", Filter); + + NTSTATUS Status = STATUS_SUCCESS; + + CCaptureFilter *CapFilter = new (NonPagedPoolNx, 'rtlf') CCaptureFilter (Filter); + + if (!CapFilter) + { + // + // Return failure if we couldn't create the filter. + // + Status = STATUS_INSUFFICIENT_RESOURCES; + + } + else + { + // Allocate memory or whatever. + Status = CapFilter->Initialize(); + + if (!NT_SUCCESS (Status)) + { + delete CapFilter; + } + else + { + Filter -> Context = reinterpret_cast <PVOID> (CapFilter); + } + + } + + DBG_LEAVE( "()=0x%08X", Status ); + return Status; +} + +NTSTATUS +CCaptureFilter::DispatchClose( + _In_ PKSFILTER Filter, + _In_ PIRP Irp +) +/*++ + +Routine Description: + + Static function for the close dispatch for the capture filter. It handles + filter cleanup. + +Arguments: + + Filter - + The AVStream filter being closed + + Irp - + The creation Irp + +Return Value: + + Success / failure + +--*/ +{ + PAGED_CODE(); + + CCaptureFilter *pFilter = reinterpret_cast <CCaptureFilter *>(Filter->Context); + + if( pFilter ) + { + pFilter->Cleanup(); + delete pFilter; + } + return STATUS_SUCCESS; +} + +void +CCaptureFilter:: +setPin( + _In_ CCapturePin *pPin, + _In_ unsigned Id +) +/*++ + +Routine Description: + + Attach a CCapturePin to the filter. + +Arguments: + + pPin - + The pin. + Id - + The pin index. + +Return Value: + + Success / failure + +--*/ +{ + PAGED_CODE( ); + + if( Id >= m_Sensor->GetPinCount() ) + { + __debugbreak(); + return; + } + + // Take out a weak reference to the pin object. + m_pinArray[Id] = pPin; +} + +CCapturePin * +CCaptureFilter:: +getPin( + _In_ unsigned Id +) +/*++ + +Routine Description: + + Get a pointer to an attached CCapturePin. + +Arguments: + + Id - + The pin index. + +Return Value: + + Success / failure + +--*/ +{ + PAGED_CODE( ); + + if( Id >= m_Sensor->GetPinCount() ) + { + __debugbreak(); + return nullptr; + } + + // Convert back to a strong reference before returning. + return m_pinArray[Id] ; +} + +NTSTATUS +CCaptureFilter:: +UpdateAllocatorFraming( + _In_ ULONG PinId +) +/*++ + +Routine Description: + + Update the Pin's Allocator Framing. + +Arguments: + + PinId - + A pin's index + +Return Value: + + Success / failure + +--*/ +{ + PAGED_CODE(); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + // Acquire the lock and update the Pin's allocator framing. + LockFilter Lock(m_pKSFilter); + + if( m_pinArray[PinId] ) + { + Status = m_pinArray[PinId]->UpdateAllocatorFraming(); + } + + DBG_LEAVE("()=0x%08X",Status); + return Status; +} + +/************************************************************************** + + Control validation and forwarding. + +**************************************************************************/ + +// Get for KSPROPERTY_CAMERACONTROL_FLASH_PROPERTY_ID +NTSTATUS +CCaptureFilter:: +GetFlash( + _Inout_ KSPROPERTY_CAMERACONTROL_FLASH_S *pFlash +) +{ + PAGED_CODE(); + + return + m_Sensor->GetFlash( pFlash ); +} + +// Set for KSPROPERTY_CAMERACONTROL_FLASH_PROPERTY_ID +NTSTATUS +CCaptureFilter:: +SetFlash( + _In_ KSPROPERTY_CAMERACONTROL_FLASH_S *pFlash +) +{ + PAGED_CODE(); + + KSPROPERTY_CAMERACONTROL_FLASH_S Caps; + + RtlZeroMemory( &Caps, sizeof(Caps) ); + NTSTATUS Status = m_Sensor->GetFlash(&Caps); + + if( NT_SUCCESS(Status) ) + { + // Assume an invalid parameter. + Status = STATUS_INVALID_PARAMETER; + + // Validate the parameters against our caps. + switch( pFlash->Flash ) + { + case KSPROPERTY_CAMERACONTROL_FLASH_OFF: + case KSPROPERTY_CAMERACONTROL_FLASH_ON: + if( Caps.Capabilities & KSPROPERTY_CAMERACONTROL_FLASH_FLAGS_MANUAL ) + { + Status = STATUS_SUCCESS; + } + break; + + case KSPROPERTY_CAMERACONTROL_FLASH_AUTO: + if( Caps.Capabilities & KSPROPERTY_CAMERACONTROL_FLASH_FLAGS_AUTO ) + { + Status = STATUS_SUCCESS; + } + break; + } + } + if( NT_SUCCESS(Status) ) + { + Status = m_Sensor->SetFlash( pFlash ); + } + + return Status; +} + +// Get for PROPSETID_VIDCAP_CAMERACONTROL_VIDEO_STABILIZATION:0 +NTSTATUS +CCaptureFilter:: +GetVideoStabMode( + _Inout_ KSPROPERTY_CAMERACONTROL_VIDEOSTABILIZATION_MODE_S *pVideoStab +) +{ + PAGED_CODE(); + + return + m_Sensor->GetVideoStabMode( pVideoStab ); +} + +// Set for PROPSETID_VIDCAP_CAMERACONTROL_VIDEO_STABILIZATION:0 +NTSTATUS +CCaptureFilter:: +SetVideoStabMode( + _In_ KSPROPERTY_CAMERACONTROL_VIDEOSTABILIZATION_MODE_S *pVideoStab +) +{ + PAGED_CODE(); + + KSPROPERTY_CAMERACONTROL_VIDEOSTABILIZATION_MODE_S Caps; + + RtlZeroMemory( &Caps, sizeof(Caps) ); + NTSTATUS Status = m_Sensor->GetVideoStabMode( &Caps ); + + DBG_ENTER("(Mode=0x%08X, Caps=0x%08X)", pVideoStab->VideoStabilizationMode, Caps.Capabilities ); + + if( NT_SUCCESS(Status) ) + { + Status = STATUS_INVALID_PARAMETER; + switch( pVideoStab->VideoStabilizationMode ) + { + case KSPROPERTY_CAMERACONTROL_VIDEOSTABILIZATION_MODE_OFF: + Status = STATUS_SUCCESS; + break; + + case KSPROPERTY_CAMERACONTROL_VIDEOSTABILIZATION_MODE_AUTO: + if( Caps.Capabilities & KSPROPERTY_CAMERACONTROL_VIDEOSTABILIZATION_MODE_FLAGS_AUTO ) + { + Status = STATUS_SUCCESS; + } + break; + + case KSPROPERTY_CAMERACONTROL_VIDEOSTABILIZATION_MODE_LOW: + case KSPROPERTY_CAMERACONTROL_VIDEOSTABILIZATION_MODE_MEDIUM: + case KSPROPERTY_CAMERACONTROL_VIDEOSTABILIZATION_MODE_HIGH: + if( Caps.Capabilities & KSPROPERTY_CAMERACONTROL_VIDEOSTABILIZATION_MODE_FLAGS_MANUAL ) + { + Status = STATUS_SUCCESS; + } + break; + } + } + if( NT_SUCCESS(Status) ) + { + Status = m_Sensor->SetVideoStabMode( pVideoStab ); + } + DBG_LEAVE("(Mode=0x%08X, Caps=0x%08X)=0x%08X", pVideoStab->VideoStabilizationMode, Caps.Capabilities, Status ); + return Status; +} + +// Get for KSPROPERTY_CAMERACONTROL_IMAGE_PIN_CAPABILITY_PROPERTY_ID +NTSTATUS +CCaptureFilter:: +GetPinDependence( + _Inout_ KSPROPERTY_CAMERACONTROL_IMAGE_PIN_CAPABILITY_S *pPinDependence +) +{ + PAGED_CODE(); + + return + m_Sensor->GetPinDependence( pPinDependence ); +} + +// +// A macro used for consistent asynchronous SET behavior. +// +#define INVOKE_SET_ASYNC( SENSOR, PROPERTY, OUTPUT, NOTIFIER ) \ + ( OUTPUT->Flags & KSCAMERA_EXTENDEDPROP_FLAG_CANCELOPERATION ) ? SENSOR->Cancel ## PROPERTY () : \ + SENSOR->Set ## PROPERTY ## Async( OUTPUT, &NOTIFIER ); + +#define INVOKE_SET_ASYNC_NOT_CANCELLABLE( SENSOR, PROPERTY, OUTPUT, NOTIFIER ) \ + ( OUTPUT->Flags & KSCAMERA_EXTENDEDPROP_FLAG_CANCELOPERATION ) ? STATUS_INVALID_PARAMETER : \ + SENSOR->Set ## PROPERTY ## Async( OUTPUT, &NOTIFIER ); + +// Get for KSPROPERTY_CAMERACONTROL_REGION_OF_INTEREST_PROPERTY_ID +NTSTATUS +CCaptureFilter::GetFocusRect( + _Inout_ KSPROPERTY_CAMERACONTROL_REGION_OF_INTEREST_S *pRoi +) +{ + PAGED_CODE(); + return m_Sensor->GetFocusRect( pRoi ); +} + +// Set for KSPROPERTY_CAMERACONTROL_REGION_OF_INTEREST_PROPERTY_ID +NTSTATUS +CCaptureFilter:: +SetFocusRect( + _In_ KSPROPERTY_CAMERACONTROL_REGION_OF_INTEREST_S *pRoi +) +{ + PAGED_CODE(); + + return m_Sensor->SetFocusRectAsync( pRoi, &m_FocusRectNotifier ); +} + +// Get KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOMODE +NTSTATUS +CCaptureFilter::GetPhotoMode( + _Inout_ CExtendedPhotoMode *pMode +) +{ + PAGED_CODE(); + + DBG_ENTER( "()" ); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pMode->isValid() && + m_Sensor->IsStillIndex( pMode->PinId ) ) + { + Status = m_Sensor->GetPhotoMode( pMode ); + } + + DBG_TRACE( "Capability=0x%016llX", pMode->Capability ); + DBG_TRACE( "PinId=%d", pMode->PinId ); + DBG_TRACE( "MaxHistoryFrames=%d", pMode->MaxHistoryFrames() ); + + DBG_LEAVE( "()=0x%08X", Status ); + return Status; +} + +// Set KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOMODE +NTSTATUS +CCaptureFilter:: +SetPhotoMode( + _In_ CExtendedPhotoMode *pMode +) +{ + PAGED_CODE(); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + DBG_ENTER( "()" ); + + if( pMode->isValid() && + m_Sensor->IsStillIndex( pMode->PinId ) && + (pMode->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) ) + { + CExtendedPhotoMode Caps(*pMode); + Status = m_Sensor->GetPhotoMode( &Caps ); + CCapturePin *pPin = getPin(pMode->PinId); + + // Should always be valid. + NT_ASSERT(pPin); + + if( NT_SUCCESS(Status) ) + { + // Assume an invalid parameter again. + Status = STATUS_INVALID_PARAMETER; + + if( (pMode->Flags & Caps.Capability) == pMode->Flags ) + { + // We don't support cancel here. + switch( pMode->Flags ) + { + case KSCAMERA_EXTENDEDPROP_PHOTOMODE_SEQUENCE: + { + // We cache the Per-Frame Settings in the filter as a simplification for the getter. + // But we can also use it here to tell us basic info about the current PFS. + PKSCAMERA_PERFRAMESETTING_HEADER pPFS = m_pPerFrameSettings; + if( pMode->SubMode() == KSCAMERA_EXTENDEDPROP_PHOTOMODE_SEQUENCE_SUB_VARIABLE && + !pPFS ) + { + DBG_TRACE( "VPS requested without Per Frame Settings." ); + break; + } + + // Reject any request for too many history frames. + if( pMode->RequestedHistoryFrames() > Caps.MaxHistoryFrames() ) + { + DBG_TRACE( "Too many history frames requested." ); + break; + } + + DBG_TRACE( "Flags=0x%08X, RequestedHistoryFrames=%d, SubMode=0x%08X", + (ULONG) pMode->Flags, + pMode->RequestedHistoryFrames(), + pMode->SubMode() ); + + // Assume the normal photo sequence case. + // For normal photo sequence, we provide history frames +1 or at least a minimum of 3 frames. + ULONG TotalFrames = pMode->RequestedHistoryFrames() + 1; + + // Modify TotalFrames for the VPS case. + // For VPS, we need LoopCount * FrameCount; but limit by the minimum(3) and maximum (20) frames. + if( KSCAMERA_EXTENDEDPROP_PHOTOMODE_SEQUENCE_SUB_VARIABLE==pMode->SubMode() ) + { + // Assume at least one loop, if the loop is infinite. + ULONG LoopCount = max( pPFS->LoopCount, 1 ); + ULONG FrameCount= pPFS->FrameCount; + + // Add in the number of future frames expected. + TotalFrames+= (LoopCount * FrameCount) -1; + + DBG_TRACE( "TotalFrames=%d, LoopCount=%d, FrameCount=%d", TotalFrames, LoopCount, FrameCount ); + } + + // Bound the frame count to minimum and maximums. + TotalFrames = + min( max( TotalFrames, IMAGE_CAPTURE_PIN_MINIMUM_FRAMES ), IMAGE_CAPTURE_PIN_MAXIMUM_FRAMES ); + DBG_TRACE( "Advertising Framing requirement: %d", TotalFrames ); + + + pPin->SetDesiredFrames(TotalFrames); + Status = STATUS_SUCCESS; + break; + } + case KSCAMERA_EXTENDEDPROP_PHOTOMODE_NORMAL: + { + // Set it back to the minimum number of frames. + pPin->SetDesiredFrames(IMAGE_CAPTURE_PIN_MINIMUM_FRAMES); + Status = STATUS_SUCCESS; + break; + } + } + + // Update allocator framing. + if( NT_SUCCESS( Status ) ) + { + Status = UpdateAllocatorFraming( pMode->PinId ); + } + + // Update the sensor object... + if( NT_SUCCESS(Status) ) + { + Status = m_Sensor->SetPhotoModeAsync( pMode, &m_PhotoModeNotifier ); + } + } + } + } + + DBG_TRACE( "Capability=0x%016llX", pMode->Capability ); + DBG_TRACE( "Flags=0x%016llX", pMode->Flags ); + DBG_TRACE( "PinId=%d", pMode->PinId ); + DBG_TRACE( "MaxHistoryFrames=%d", pMode->MaxHistoryFrames() ); + DBG_TRACE( "RequestedHistoryFrames=%d", pMode->RequestedHistoryFrames() ); + DBG_TRACE( "SubMode=0x%08X", pMode->SubMode() ); + DBG_LEAVE( "()=0x%08X", Status ); + return Status; +} + +/* + * KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOFRAMERATE Get Handler + */ +NTSTATUS +CCaptureFilter::GetPhotoFrameRate( + _Inout_ CExtendedProperty *pFrameRate +) +{ + PAGED_CODE(); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pFrameRate->isValid() && + m_Sensor->IsStillIndex(pFrameRate->PinId) ) + { + ULONGLONG TimePerFrame = m_Sensor->GetPhotoFrameRate(pFrameRate->PinId); + if( TimePerFrame > ULONG_MAX ) + { + // Handle very large (slow) frame rates in seconds. + pFrameRate->m_Value.Value.ratio.HighPart = 1; + pFrameRate->m_Value.Value.ratio.LowPart = (ULONG) (TimePerFrame / ONESECOND); + } + else + { + // Handle smaller frame rates as 100ns units. + pFrameRate->m_Value.Value.ratio.HighPart = ONESECOND; + pFrameRate->m_Value.Value.ratio.LowPart = (ULONG) TimePerFrame; + } + Status = STATUS_SUCCESS; + } + + DBG_LEAVE("(PinId=%d, estimated FrameRate=%d/%d)=0x%08X", + pFrameRate->PinId, + pFrameRate->m_Value.Value.ratio.HighPart, + pFrameRate->m_Value.Value.ratio.LowPart, + Status ); + return Status; +} + +/* + * KSPROPERTY_CAMERACONTROL_EXTENDED_MAXVIDFPS_PHOTORES Get Handler + */ +NTSTATUS +CCaptureFilter:: +GetMaxVideoFpsForPhotoRes( + _Inout_ CExtendedMaxVideoFpsForPhotoRes *pFps +) +{ + PAGED_CODE(); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pFps->isValid() && + pFps->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE && + pFps->Capability == 0 && + pFps->Flags == 0 ) + { + Status = m_Sensor->GetMaxVideoFpsForPhotoRes( pFps ); + } + return Status; +} + +/* + * KSPROPERTY_CAMERACONTROL_EXTENDED_MAXVIDFPS_PHOTORES Set Handler + */ +NTSTATUS +CCaptureFilter::SetMaxVideoFpsForPhotoRes( + _In_ CExtendedMaxVideoFpsForPhotoRes *pFps +) +{ + PAGED_CODE(); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pFps->isValid() && + pFps->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE && + pFps->Capability == 0 && + pFps->Flags == 0 ) + { + Status = m_Sensor->SetMaxVideoFpsForPhotoRes( pFps ); + } + return Status; +} + +/* + * KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOMAXFRAMERATE Get Handler + */ +NTSTATUS +CCaptureFilter::GetPhotoMaxFrameRate( + _Inout_ CExtendedProperty *pFrameRate +) +{ + PAGED_CODE(); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pFrameRate->isValid() && + m_Sensor->IsStillIndex(pFrameRate->PinId) ) + { + Status = m_Sensor->GetPhotoMaxFrameRate( pFrameRate ); + } + return Status; +} + +/* + * KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOMAXFRAMERATE Set Handler + */ +NTSTATUS +CCaptureFilter:: +SetPhotoMaxFrameRate( + _In_ CExtendedProperty *pFrameRate +) +{ + PAGED_CODE(); + + DBG_ENTER("(MaxFrameRate = %d/%d)", + pFrameRate->m_Value.Value.ratio.HighPart, + pFrameRate->m_Value.Value.ratio.LowPart ); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pFrameRate->isValid() && + m_Sensor->IsStillIndex( pFrameRate->PinId ) && + (pFrameRate->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) ) + { + // Don't allow either the numerator or denominator alone to be 0. + // We don't want a rate of 0 fps or undefined. + if( pFrameRate->m_Value.Value.ll == 0 || + ( pFrameRate->m_Value.Value.ratio.LowPart != 0 && + pFrameRate->m_Value.Value.ratio.HighPart != 0 ) ) + { + // Take what we're given here; SetPhotoFrameRate handles default setting. + DBG_TRACE("[Override] MaxFrameRate = %d/%d", + pFrameRate->m_Value.Value.ratio.HighPart, + pFrameRate->m_Value.Value.ratio.LowPart ); + + Status = m_Sensor->SetPhotoMaxFrameRateAsync( pFrameRate, &m_PhotoMaxFrameRateNotifier ); + } + } + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOTRIGGERTIME +NTSTATUS +CCaptureFilter:: +GetTriggerTime( + _Inout_ CExtendedProperty *pTriggerTime +) +{ + PAGED_CODE(); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pTriggerTime->isValid() && + m_Sensor->IsStillIndex(pTriggerTime->PinId) ) + { + Status = m_Sensor->GetTriggerTime( pTriggerTime ); + } + return Status; +} + +// Set KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOTRIGGERTIME +NTSTATUS +CCaptureFilter:: +SetTriggerTime( + _In_ CExtendedProperty *pTriggerTime +) +{ + PAGED_CODE(); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pTriggerTime->isValid() && + pTriggerTime->Capability == 0 && + m_Sensor->IsStillIndex(pTriggerTime->PinId) ) + { + Status = m_Sensor->SetTriggerTime( pTriggerTime ); + } + return Status; +} + +/* + * KSPROPERTY_CAMERACONTROL_EXTENDED_WARMSTART + */ +NTSTATUS +CCaptureFilter:: +GetWarmStart( + _Inout_ CExtendedProperty *pWarmStart +) +{ + PAGED_CODE(); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pWarmStart->isValid() && + m_Sensor->IsValidIndex( pWarmStart->PinId ) ) + { + Status = m_Sensor->GetWarmStart( pWarmStart ); + } + DBG_LEAVE("(PinId=%d, Flags=0x%016llX, Cap=0x%016llX)=0x%08X", + pWarmStart->PinId, pWarmStart->Flags, pWarmStart->Capability, Status ); + return Status; +} + +/* + * KSPROPERTY_CAMERACONTROL_EXTENDED_WARMSTART Set Handler + */ +NTSTATUS +CCaptureFilter::SetWarmStart( + _In_ CExtendedProperty *pWarmStart +) +{ + PAGED_CODE(); + DBG_LEAVE("(PinId=%d, Flags=0x%016llX, Cap=0x%016llX)", + pWarmStart->PinId, pWarmStart->Flags, pWarmStart->Capability ); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pWarmStart->isValid() && + m_Sensor->IsValidIndex( pWarmStart->PinId ) && + (pWarmStart->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) ) + { + CExtendedProperty Caps(*pWarmStart); + Status = m_Sensor->GetWarmStart( &Caps ); + + if( NT_SUCCESS(Status ) ) + { + if( pWarmStart->Flags == (pWarmStart->Flags & Caps.Capability) ) + { + Status = INVOKE_SET_ASYNC( m_Sensor, WarmStart, pWarmStart, m_WarmStartNotifier ); + } + } + else + { + Status = STATUS_INVALID_PARAMETER; + } + } + + DBG_LEAVE("()=0x%08X", Status ); + return Status; +} + +// Set KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOTHUMBNAIL +NTSTATUS +CCaptureFilter:: +SetThumbnail( + _In_ CExtendedProperty *pThumbnail +) +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + DBG_ENTER("()"); + + // Validate + if( (pThumbnail->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) && + pThumbnail->isValid() && + m_Sensor->IsStillIndex(pThumbnail->PinId) ) + { + CExtendedProperty Caps; + Status = m_Sensor->GetThumbnail( &Caps ); + + if( NT_SUCCESS(Status) ) + { + if( pThumbnail->Flags == (Caps.Capability & pThumbnail->Flags) ) + { + Status = INVOKE_SET_ASYNC( m_Sensor, Thumbnail, pThumbnail, m_ThumbnailNotifier ); + } + else + { + Status = STATUS_INVALID_PARAMETER; + } + } + } + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOTHUMBNAIL +NTSTATUS +CCaptureFilter:: +GetThumbnail( + _Inout_ CExtendedProperty *pThumbnail +) +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + DBG_ENTER("()"); + + // Validate + if( pThumbnail->isValid() && + m_Sensor->IsStillIndex(pThumbnail->PinId) ) + { + Status = m_Sensor->GetThumbnail( pThumbnail ); + } + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_EXTENDED_SCENEMODE +NTSTATUS +CCaptureFilter:: +GetSceneMode( + _Inout_ CExtendedProperty *pSceneMode +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pSceneMode->isValid() && + pSceneMode->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE ) + { + Status = m_Sensor->GetSceneMode( pSceneMode ); + } + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Set KSPROPERTY_CAMERACONTROL_EXTENDED_SCENEMODE +NTSTATUS +CCaptureFilter:: +SetSceneMode( + _In_ CExtendedProperty *pSceneMode +) +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + DBG_ENTER("()"); + + if( (pSceneMode->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) && + pSceneMode->isValid() && + pSceneMode->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE ) + { + CExtendedProperty Caps; + Status = m_Sensor->GetSceneMode( &Caps ); + + if( NT_SUCCESS(Status) ) + { + if( pSceneMode->Flags == (Caps.Capability & pSceneMode->Flags) ) + { + Status = INVOKE_SET_ASYNC_NOT_CANCELLABLE( m_Sensor, SceneMode, pSceneMode, m_SceneModeNotifier ); + } + else + { + Status = STATUS_INVALID_PARAMETER; + } + } + } + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_EXTENDED_TORCHMODE +NTSTATUS +CCaptureFilter:: +GetTorchMode( + _Inout_ CExtendedProperty *pTorchMode +) +{ + PAGED_CODE(); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pTorchMode->isValid() && + pTorchMode->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE ) + { + Status = m_Sensor->GetTorchMode( pTorchMode ); + } + DBG_LEAVE("(PinId=%d, Flags=0x%016llX, Cap=0x%016llX)=0x%08X", + pTorchMode->PinId, pTorchMode->Flags, pTorchMode->Capability, Status ); + return Status; +} + +// Set KSPROPERTY_CAMERACONTROL_EXTENDED_TORCHMODE +NTSTATUS +CCaptureFilter:: +SetTorchMode( + _In_ CExtendedProperty *pTorchMode +) +{ + PAGED_CODE(); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( !(pTorchMode->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) && + pTorchMode->isValid() && + pTorchMode->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE && + pTorchMode->m_Value.Value.ul <= 100 ) + { + CExtendedProperty Caps(*pTorchMode); + Status = m_Sensor->GetTorchMode(&Caps); + + if( NT_SUCCESS(Status) ) + { + // Assume an invalid parameter. + Status = STATUS_INVALID_PARAMETER; + + if( pTorchMode->Flags == (pTorchMode->Flags & Caps.Capability) ) + { + switch( pTorchMode->Flags ) + { + case KSCAMERA_EXTENDEDPROP_VIDEOTORCH_OFF: + case KSCAMERA_EXTENDEDPROP_VIDEOTORCH_ON: + case KSCAMERA_EXTENDEDPROP_VIDEOTORCH_ON_ADJUSTABLEPOWER: + Status = m_Sensor->SetTorchMode( pTorchMode ); + break; + } + } + } + } + DBG_LEAVE("(PinId=%d, Flags=0x%016llX, Cap=0x%016llX)=0x%08X", + pTorchMode->PinId, pTorchMode->Flags, pTorchMode->Capability, Status ); + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_EXTENDED_FLASHMODE +NTSTATUS +CCaptureFilter:: +GetExtendedFlash( + _Inout_ CExtendedProperty *pFlash +) +{ + PAGED_CODE(); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pFlash->isValid() && + pFlash->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE) + { + Status = m_Sensor->GetExtendedFlash( pFlash ); + } + DBG_LEAVE("(PinId=%d, Flags=0x%016llX, Cap=0x%016llX)=0x%08X", + pFlash->PinId, pFlash->Flags, pFlash->Capability, Status ); + return Status; +} + +// Set KSPROPERTY_CAMERACONTROL_EXTENDED_FLASHMODE +NTSTATUS +CCaptureFilter:: +SetExtendedFlash( + _In_ CExtendedProperty *pFlash +) +{ + PAGED_CODE(); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( !(pFlash->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) && + pFlash->isValid() && + pFlash->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE) + { + CExtendedProperty Caps; + Status = m_Sensor->GetExtendedFlash( &Caps ); + + if( NT_SUCCESS(Status) ) + { + // Assume an invalid parameter. + Status = STATUS_INVALID_PARAMETER; + + if( pFlash->Flags == (pFlash->Flags & Caps.Capability) ) + { + // Validate flash settings. + // First validate the basic flash controls + switch( pFlash->Flags & KSCAMERA_EXTENDEDPROP_FLASH_MODE_MASK ) + { + // Valid combinations + case KSCAMERA_EXTENDEDPROP_FLASH_OFF: + case KSCAMERA_EXTENDEDPROP_FLASH_ON: + case KSCAMERA_EXTENDEDPROP_FLASH_ON_ADJUSTABLEPOWER: + case KSCAMERA_EXTENDEDPROP_FLASH_AUTO: + case KSCAMERA_EXTENDEDPROP_FLASH_AUTO_ADJUSTABLEPOWER: + Status = STATUS_SUCCESS; + break; + } + + // Validate red eye reduction, single flash & multiflash supported. + if( !(pFlash->Flags & + ( KSCAMERA_EXTENDEDPROP_FLASH_REDEYEREDUCTION | + KSCAMERA_EXTENDEDPROP_FLASH_SINGLEFLASH | + KSCAMERA_EXTENDEDPROP_FLASH_MULTIFLASHSUPPORTED )) || + (pFlash->Flags & KSCAMERA_EXTENDEDPROP_FLASH_MODE_MASK) != KSCAMERA_EXTENDEDPROP_FLASH_OFF ) + { + Status = STATUS_SUCCESS; + } + + // Validate Flash Assistant parameters + switch( pFlash->Flags & KSCAMERA_EXTENDEDPROP_FLASH_ASSISTANT_MASK ) + { + // Valid combinations + case KSCAMERA_EXTENDEDPROP_FLASH_ASSISTANT_OFF: + case KSCAMERA_EXTENDEDPROP_FLASH_ASSISTANT_ON: + case KSCAMERA_EXTENDEDPROP_FLASH_ASSISTANT_AUTO: + Status = STATUS_SUCCESS; + break; + } + } + } + } + + if( NT_SUCCESS(Status) ) + { + Status = m_Sensor->SetExtendedFlash( pFlash ); + } + + DBG_LEAVE("(PinId=%d, Flags=0x%016llX, Cap=0x%016llX)=0x%08X", + pFlash->PinId, pFlash->Flags, pFlash->Capability, Status ); + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_EXTENDED_OPTIMIZATIONHINT +NTSTATUS +CCaptureFilter:: +GetOptimizationHint( + _Inout_ CExtendedProperty *pHint +) +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pHint->isValid() && + !(pHint->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) && + pHint->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE ) + { + Status = m_Sensor->GetOptimizationHint(pHint); + } + DBG_LEAVE("(PinId=%d, Flags=0x%016llX, Cap=0x%016llX)=0x%08X", + pHint->PinId, pHint->Flags, pHint->Capability, Status ); + return Status; +} + +// Set KSPROPERTY_CAMERACONTROL_EXTENDED_OPTIMIZATIONHINT +NTSTATUS +CCaptureFilter:: +SetOptimizationHint( + _In_ CExtendedProperty *pHint +) +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pHint->isValid() && + !(pHint->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) && + pHint->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE ) + { + CExtendedProperty Caps(*pHint); + Status = m_Sensor->GetOptimizationHint(&Caps); + + if( NT_SUCCESS(Status) ) + { + // Assume an invalid parameter. + Status = STATUS_INVALID_PARAMETER; + + if( pHint->Flags == (pHint->Flags & Caps.Capability) ) + { + // Inherit the previous primary use flag settings, if they were not set here. + if( KSCAMERA_EXTENDEDPROP_OPTIMIZATION_DEFAULT == pHint->Flags || + 0 == (pHint->Flags & KSCAMERA_EXTENDEDPROP_OPTIMIZATION_PRIMARYUSE_MASK) ) + { + pHint->Flags |= (Caps.Flags & KSCAMERA_EXTENDEDPROP_OPTIMIZATION_PRIMARYUSE_MASK); + } + else + { + // Inherit the previous perf flag settings, if they were not set here and if DEFAULT is not set. + if( 0 == (pHint->Flags & KSCAMERA_EXTENDEDPROP_OPTIMIZATION_PERF_MASK) ) + { + pHint->Flags |= (Caps.Flags & KSCAMERA_EXTENDEDPROP_OPTIMIZATION_PERF_MASK); + } + } + + // Make sure the requested flags are a valid capability combination. + switch( pHint->Flags ) + { + case KSCAMERA_EXTENDEDPROP_OPTIMIZATION_PHOTO: + case KSCAMERA_EXTENDEDPROP_OPTIMIZATION_PHOTO | KSCAMERA_EXTENDEDPROP_OPTIMIZATION_QUALITY: + case KSCAMERA_EXTENDEDPROP_OPTIMIZATION_PHOTO | KSCAMERA_EXTENDEDPROP_OPTIMIZATION_LATENCY: + case KSCAMERA_EXTENDEDPROP_OPTIMIZATION_PHOTO | KSCAMERA_EXTENDEDPROP_OPTIMIZATION_POWER : + case KSCAMERA_EXTENDEDPROP_OPTIMIZATION_VIDEO: + case KSCAMERA_EXTENDEDPROP_OPTIMIZATION_VIDEO | KSCAMERA_EXTENDEDPROP_OPTIMIZATION_QUALITY: + case KSCAMERA_EXTENDEDPROP_OPTIMIZATION_VIDEO | KSCAMERA_EXTENDEDPROP_OPTIMIZATION_LATENCY: + case KSCAMERA_EXTENDEDPROP_OPTIMIZATION_VIDEO | KSCAMERA_EXTENDEDPROP_OPTIMIZATION_POWER : + case KSCAMERA_EXTENDEDPROP_OPTIMIZATION_PHOTO | + KSCAMERA_EXTENDEDPROP_OPTIMIZATION_QUALITY | + KSCAMERA_EXTENDEDPROP_OPTIMIZATION_LATENCY : + case KSCAMERA_EXTENDEDPROP_OPTIMIZATION_PHOTO | + KSCAMERA_EXTENDEDPROP_OPTIMIZATION_QUALITY | + KSCAMERA_EXTENDEDPROP_OPTIMIZATION_POWER : + case KSCAMERA_EXTENDEDPROP_OPTIMIZATION_PHOTO | + KSCAMERA_EXTENDEDPROP_OPTIMIZATION_LATENCY | + KSCAMERA_EXTENDEDPROP_OPTIMIZATION_POWER : + case KSCAMERA_EXTENDEDPROP_OPTIMIZATION_VIDEO | + KSCAMERA_EXTENDEDPROP_OPTIMIZATION_QUALITY | + KSCAMERA_EXTENDEDPROP_OPTIMIZATION_LATENCY : + case KSCAMERA_EXTENDEDPROP_OPTIMIZATION_VIDEO | + KSCAMERA_EXTENDEDPROP_OPTIMIZATION_QUALITY | + KSCAMERA_EXTENDEDPROP_OPTIMIZATION_POWER : + case KSCAMERA_EXTENDEDPROP_OPTIMIZATION_VIDEO | + KSCAMERA_EXTENDEDPROP_OPTIMIZATION_LATENCY | + KSCAMERA_EXTENDEDPROP_OPTIMIZATION_POWER : + Status = m_Sensor->SetOptimizationHint(pHint); + break; + } + } + } + } + DBG_LEAVE("(PinId=%d, Flags=0x%016llX, Cap=0x%016llX)=0x%08X", + pHint->PinId, pHint->Flags, pHint->Capability, Status ); + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_EXTENDED_FIELDOFVIEW +NTSTATUS +CCaptureFilter:: +GetFieldOfView( + _Inout_ CExtendedFieldOfView *pFieldOfView +) +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pFieldOfView->isValid() && + pFieldOfView->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE ) + { + Status = m_Sensor->GetFieldOfView(pFieldOfView); + } + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_EXTENDED_CAMERAANGLEOFFSET +NTSTATUS +CCaptureFilter:: +GetCameraAngleOffset( + _Inout_ CExtendedCameraAngleOffset *pAngleOffset +) +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pAngleOffset->isValid() && + pAngleOffset->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE ) + { + Status = m_Sensor->GetCameraAngleOffset(pAngleOffset); + } + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_EXTENDED_METADATA +NTSTATUS +CCaptureFilter:: +GetMetadata( + _Inout_ CExtendedMetadata *pMetadata +) +{ + PAGED_CODE(); + + if( pMetadata->PinId >= m_Sensor->GetPinCount() ) + { + return STATUS_INVALID_PARAMETER; + } + + return m_Sensor->GetMetadata( pMetadata ); +} + +// Set KSPROPERTY_CAMERACONTROL_EXTENDED_METADATA +NTSTATUS +CCaptureFilter:: +SetMetadata( + _In_ CExtendedMetadata *pMetadata +) +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( !(pMetadata->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) && + pMetadata->isValid() && + m_Sensor->IsValidIndex( pMetadata->PinId ) ) + { + if( m_pinArray[pMetadata->PinId] && + m_pinArray[pMetadata->PinId]->GetState() == PinRunning ) + { + Status = STATUS_INVALID_DEVICE_REQUEST; + } + else + { + Status = m_Sensor->SetMetadata( pMetadata ); + } + } + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_EXTENDED_ISO +NTSTATUS +CCaptureFilter:: +GetIso( + _Inout_ CExtendedProperty *pIso +) +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pIso->isValid() && + m_Sensor->IsStillIndex( pIso->PinId ) ) + { + Status = m_Sensor->GetIso(pIso); + } + + DBG_LEAVE("(PinId=%d, Flags=0x%016llX, Cap=0x%016llX)=0x%08X", + pIso->PinId, pIso->Flags, pIso->Capability, Status ); + return Status; +} + +// Set KSPROPERTY_CAMERACONTROL_EXTENDED_ISO +NTSTATUS +CCaptureFilter:: +SetIso( + _In_ CExtendedProperty *pIso +) +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + DBG_ENTER("(Flags=0x%016llX)", pIso->Flags); + + if( (pIso->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) && + pIso->isValid() && + m_Sensor->IsStillIndex( pIso->PinId ) ) + { + CExtendedProperty Caps; + Status = m_Sensor->GetIso( &Caps ); + + if( NT_SUCCESS(Status) ) + { + // Assume an invalid parameter. + Status = STATUS_INVALID_PARAMETER; + + if( pIso->Flags == (pIso->Flags & Caps.Capability) ) + { + // Make sure only one preset was set. + ULONGLONG presets = pIso->Flags & + ( 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 ) ; + + DBG_TRACE("presets=0x%016llX", presets); + + // Check to see if there is exactly one set. + if( presets && ( (presets-1) & presets ) == 0 ) + { + Status = INVOKE_SET_ASYNC( m_Sensor, Iso, pIso, m_IsoNotifier ); + } + } + } + } + + DBG_LEAVE("(PinId=%d, Flags=0x%016llX, Cap=0x%016llX)=0x%08X", + pIso->PinId, pIso->Flags, pIso->Capability, Status ); + + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_EXTENDED_EVCOMPENSATION +NTSTATUS +CCaptureFilter:: +GetEvCompensation( + _Inout_ CExtendedEvCompensation *pEvComp +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pEvComp->isValid() && + pEvComp->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE ) + { + Status = m_Sensor->GetEvCompensation( pEvComp ); + } + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Set KSPROPERTY_CAMERACONTROL_EXTENDED_EVCOMPENSATION +NTSTATUS +CCaptureFilter:: +SetEvCompensation( + _In_ CExtendedEvCompensation *pEvComp +) +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + DBG_ENTER("()"); + if( (pEvComp->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) && + pEvComp->isValid() && + pEvComp->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE ) + { + CExtendedEvCompensation Caps; + Status = m_Sensor->GetEvCompensation( &Caps ); + + if( NT_SUCCESS(Status) ) + { + // Assume an invalid parameter. + Status = STATUS_INVALID_PARAMETER; + + if( (pEvComp->Flags & Caps.Capability ) == pEvComp->Flags ) + { + Status = INVOKE_SET_ASYNC( m_Sensor, EvCompensation, pEvComp, m_EvCompensationNotifier ); + } + } + } + + DBG_LEAVE("(PinId=%d, Flags=0x%016llX, Cap=0x%016llX)=0x%08X", + pEvComp->PinId, pEvComp->Flags, pEvComp->Capability, Status ); + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_EXTENDED_WHITEBALANCEMODE +NTSTATUS +CCaptureFilter:: +GetWhiteBalance( + _Inout_ CExtendedVidProcSetting *pWhiteBalance +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pWhiteBalance->isValid() && + pWhiteBalance->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE ) + { + Status = m_Sensor->GetWhiteBalance( pWhiteBalance ); + } + + DBG_LEAVE("(PinId=%d, Flags=0x%016llX, Cap=0x%016llX, Mode=0x%08X, Val=0x%016llX)=0x%08X", + pWhiteBalance->PinId, pWhiteBalance->Flags, pWhiteBalance->Capability, + pWhiteBalance->Mode(), pWhiteBalance->GetLONGLONG(), Status ); + return Status; +} + +// Set KSPROPERTY_CAMERACONTROL_EXTENDED_WHITEBALANCEMODE +NTSTATUS +CCaptureFilter:: +SetWhiteBalance( + _In_ CExtendedVidProcSetting *pWhiteBalance +) +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + DBG_ENTER("()"); + if( (pWhiteBalance->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) && + pWhiteBalance->isValid() && + pWhiteBalance->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE ) + { + CExtendedVidProcSetting Caps; + Status = m_Sensor->GetWhiteBalance( &Caps ); + + if( NT_SUCCESS(Status) ) + { + if( (pWhiteBalance->Flags & Caps.Capability ) == pWhiteBalance->Flags ) + { + switch( pWhiteBalance->Flags ) + { + case KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO: + break; + case KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO | KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK: + case KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK: + pWhiteBalance->Flags = KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO | KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK; + break; + + case KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL: + switch( pWhiteBalance->Mode() ) + { + case KSCAMERA_EXTENDEDPROP_WHITEBALANCE_TEMPERATURE: + Status = Caps.BoundsCheck( pWhiteBalance->GetLONGLONG() ); + break; + + case KSCAMERA_EXTENDEDPROP_WHITEBALANCE_PRESET: + switch( pWhiteBalance->GetLONGLONG() ) + { + case KSCAMERA_EXTENDEDPROP_WBPRESET_CLOUDY: + case KSCAMERA_EXTENDEDPROP_WBPRESET_DAYLIGHT: + case KSCAMERA_EXTENDEDPROP_WBPRESET_FLASH: + case KSCAMERA_EXTENDEDPROP_WBPRESET_FLUORESCENT: + case KSCAMERA_EXTENDEDPROP_WBPRESET_TUNGSTEN: + case KSCAMERA_EXTENDEDPROP_WBPRESET_CANDLELIGHT: + break; + + default: + Status = STATUS_INVALID_PARAMETER; + break; + } + break; + + default: + Status = STATUS_INVALID_PARAMETER; + break; + } + break; + + default: + Status = STATUS_INVALID_PARAMETER; + break; + } + + if( NT_SUCCESS(Status) ) + { + Status = INVOKE_SET_ASYNC( m_Sensor, WhiteBalance, pWhiteBalance, m_WhiteBalanceNotifier ); + } + } + else + { + Status = STATUS_INVALID_PARAMETER; + } + } + } + + DBG_LEAVE("(PinId=%d, Flags=0x%016llX, Cap=0x%016llX, Mode=0x%08X, Val=0x%016llX)=0x%08X", + pWhiteBalance->PinId, pWhiteBalance->Flags, pWhiteBalance->Capability, + pWhiteBalance->Mode(), pWhiteBalance->GetLONGLONG(), Status ); + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_EXTENDED_EXPOSUREMODE +NTSTATUS +CCaptureFilter:: +GetExposure( + _Inout_ CExtendedVidProcSetting *pExposure +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pExposure->isValid() && + pExposure->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE ) + { + Status = m_Sensor->GetExposure( pExposure ); + } + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Set KSPROPERTY_CAMERACONTROL_EXTENDED_EXPOSUREMODE +NTSTATUS +CCaptureFilter:: +SetExposure( + _In_ CExtendedVidProcSetting *pExposure +) +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + DBG_ENTER("()"); + if( (pExposure->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) && + pExposure->isValid() && + pExposure->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE ) + { + CExtendedVidProcSetting Caps; + Status = m_Sensor->GetExposure( &Caps ); + + if( NT_SUCCESS(Status) ) + { + if( (pExposure->Flags & Caps.Capability ) == pExposure->Flags ) + { + if( pExposure->Flags == KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL ) + { + Status = Caps.BoundsCheck( pExposure->GetULONGLONG() ); + } + + if( NT_SUCCESS(Status) ) + { + Status = INVOKE_SET_ASYNC( m_Sensor, Exposure, pExposure, m_ExposureNotifier ); + } + } + else + { + Status = STATUS_INVALID_PARAMETER; + } + } + } + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_EXTENDED_FOCUSMODE +NTSTATUS +CCaptureFilter:: +GetFocus( + _Inout_ CExtendedVidProcSetting *pFocus +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pFocus->isValid() && + pFocus->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE ) + { + Status = m_Sensor->GetFocus( pFocus ); + } + + DBG_LEAVE("(FocusMode=0x%016llX)=0x%08X", pFocus->Flags, Status); + return Status; +} + +// Set KSPROPERTY_CAMERACONTROL_EXTENDED_FOCUSMODE +NTSTATUS +CCaptureFilter:: +SetFocus( + _In_ CExtendedVidProcSetting *pFocus +) +{ + PAGED_CODE(); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + ULONGLONG Flags = pFocus->Flags; + + DBG_ENTER("(Preset Flags=0x%016llX)", Flags); + + CExtendedVidProcSetting Caps(*pFocus); + + // This part is just setting validation. + if( (pFocus->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) && + pFocus->isValid() && + pFocus->Mode() == 0 && + pFocus->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE ) + { + Status = m_Sensor->GetFocus( &Caps ); + } + + if( NT_SUCCESS(Status) ) + { + // Make sure we have a valid combinations of Flags + switch( Flags & + (KSCAMERA_EXTENDEDPROP_FOCUS_MODE_MASK | + KSCAMERA_EXTENDEDPROP_FOCUS_MODE_ADVANCED_MASK) ) + { + // Auto-focus combinations: + case KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO: + case KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO | + KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK: + case KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO | + KSCAMERA_EXTENDEDPROP_FOCUS_REGIONBASED: + case KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO | + KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK | + KSCAMERA_EXTENDEDPROP_FOCUS_REGIONBASED: + case KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO | + KSCAMERA_EXTENDEDPROP_FOCUS_DRIVERFALLBACK_OFF: + case KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO | + KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK | + KSCAMERA_EXTENDEDPROP_FOCUS_DRIVERFALLBACK_OFF: + case KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO | + KSCAMERA_EXTENDEDPROP_FOCUS_REGIONBASED | + KSCAMERA_EXTENDEDPROP_FOCUS_DRIVERFALLBACK_OFF: + case KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO | + KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK | + KSCAMERA_EXTENDEDPROP_FOCUS_REGIONBASED | + KSCAMERA_EXTENDEDPROP_FOCUS_DRIVERFALLBACK_OFF: + break; + + // Continuous-focus combinations: + case KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS: + case KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS | + KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUSLOCK: + case KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS | + KSCAMERA_EXTENDEDPROP_FOCUS_REGIONBASED: + case KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS | + KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUSLOCK | + KSCAMERA_EXTENDEDPROP_FOCUS_REGIONBASED: + case KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS | + KSCAMERA_EXTENDEDPROP_FOCUS_DRIVERFALLBACK_OFF: + case KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS | + KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUSLOCK | + KSCAMERA_EXTENDEDPROP_FOCUS_DRIVERFALLBACK_OFF: + case KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS | + KSCAMERA_EXTENDEDPROP_FOCUS_REGIONBASED | + KSCAMERA_EXTENDEDPROP_FOCUS_DRIVERFALLBACK_OFF: + case KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS | + KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUSLOCK | + KSCAMERA_EXTENDEDPROP_FOCUS_REGIONBASED | + KSCAMERA_EXTENDEDPROP_FOCUS_DRIVERFALLBACK_OFF: + break; + + // Manual stands alone. + case KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL: + Status = BoundsCheckSigned( + pFocus->GetLONG(), + Caps.m_Setting ); + + if( !NT_SUCCESS(Status) ) + { + DBG_TRACE( "ERROR: Focus request out of bounds. Value=%d", pFocus->GetLONG() ); + } + break; + + // Unlock must stand alone. + // Also note that by definition unlock is accepted regardless of our current state. + case KSCAMERA_EXTENDEDPROP_FOCUS_UNLOCK: + break; + + // Lock can stand alone. + case KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK: + // Make sure we are actually being asked during an auto or continuous. + if( !(Caps.Flags & + (KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO | KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS)) ) + { + // This is an ambiguous case under the WinBlue DDI. However, + // producing an error code here will cause a test failure. + // Instead we will silently consume the error and just skip this + // request. + // + // Actually the WinBlue WinRT layer interprets a "Manual Preset" as + // a LOCK-only request when there is no value involved. That is kind + // rediculous since the value is sent without considering the previous + // mode. Instead, it thinks that just setting a LOCK-only mode is + // synonymous with "Manual at the current position." + // + // Therefore, our interpretation will be, If we're in manual, we can + // just silently consume the entire request and do nothing. + if( Caps.Flags & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL ) + { + Status = STATUS_INVALID_LOCK_SEQUENCE; + } + else + { + Status = STATUS_INVALID_PARAMETER; + } + } + break; + + // Anything else is just wrong. + default: + Status = STATUS_INVALID_PARAMETER; + break; + } + } + + // Validate focus ranges. + if( NT_SUCCESS(Status) ) + { + // If AUTO or CONTINUOUS is requested, we may support RANGE flags. + if( (Flags & + (KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO | + KSCAMERA_EXTENDEDPROP_FOCUS_CONTINUOUS)) ) + { + switch( Flags & KSCAMERA_EXTENDEDPROP_FOCUS_RANGE_MASK ) + { + case KSCAMERA_EXTENDEDPROP_FOCUS_RANGE_MACRO: + case KSCAMERA_EXTENDEDPROP_FOCUS_RANGE_NORMAL: + case KSCAMERA_EXTENDEDPROP_FOCUS_RANGE_FULLRANGE: + // Depreciated flags are not supported: + //case KSCAMERA_EXTENDEDPROP_FOCUS_RANGE_INFINITY: + //case KSCAMERA_EXTENDEDPROP_FOCUS_RANGE_HYPERFOCAL: + case 0: + break; + + default: + Status = STATUS_INVALID_PARAMETER; + break; + } + } + // Otherwise no RANGE flags are permitted. + else if( Flags & KSCAMERA_EXTENDEDPROP_FOCUS_RANGE_MASK ) + { + Status = STATUS_INVALID_PARAMETER; + } + } + + // Validate focus distances. + if( NT_SUCCESS(Status) ) + { + // If MANUAL is requested, we may support DISTANCE flags. + if( Flags & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL ) + { + switch( Flags & KSCAMERA_EXTENDEDPROP_FOCUS_DISTANCE_MASK ) + { + case KSCAMERA_EXTENDEDPROP_FOCUS_DISTANCE_INFINITY: + case KSCAMERA_EXTENDEDPROP_FOCUS_DISTANCE_HYPERFOCAL: + case KSCAMERA_EXTENDEDPROP_FOCUS_DISTANCE_NEAREST: + case 0: + break; + + default: + Status = STATUS_INVALID_PARAMETER; + break; + } + } + // Otherwise no DISTANCE flags are permitted. + else if( Flags & KSCAMERA_EXTENDEDPROP_FOCUS_DISTANCE_MASK ) + { + Status = STATUS_INVALID_PARAMETER; + } + } + + if( NT_SUCCESS(Status) ) + { + Status = INVOKE_SET_ASYNC( m_Sensor, Focus, pFocus, m_FocusNotifier ); + } + // This is the failure case. In this case, we don't change state; but + // if we were ASYNC, we need to signal the client that we completed. + else + { + // Don't need to set the event if this was [erroneously] an sync request. + if( pFocus->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL ) + { + m_FocusNotifier.Set(); + } + + // Silently consume Lock after Manual requests: + if( STATUS_INVALID_LOCK_SEQUENCE == Status ) + { + Status = STATUS_SUCCESS; + } + } + DBG_LEAVE("(Preset Flags=0x%016llX)=0x%08X", Flags, Status); + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOCONFIRMATION +NTSTATUS +CCaptureFilter:: +GetPhotoConfirmation( + _Inout_ CExtendedProperty *pConfirmation +) +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pConfirmation->isValid() && + pConfirmation->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE ) + { + Status = m_Sensor->GetPhotoConfirmation( pConfirmation ); + } + return Status; +} + +// Set KSPROPERTY_CAMERACONTROL_EXTENDED_PHOTOCONFIRMATION +NTSTATUS +CCaptureFilter:: +SetPhotoConfirmation( + _In_ CExtendedProperty *pConfirmation +) +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( !(pConfirmation->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) && + pConfirmation->isValid() && + pConfirmation->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE ) + { + switch( pConfirmation->Flags ) + { + case KSCAMERA_EXTENDEDPROP_PHOTOCONFIRMATION_ON: + case KSCAMERA_EXTENDEDPROP_PHOTOCONFIRMATION_OFF: + Status = m_Sensor->SetPhotoConfirmation( pConfirmation ); + break; + } + } + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_PERFRAMESETTING_CAPABILITY +NTSTATUS +CCaptureFilter::GetPFSCaps( + _In_ PIRP pIrp, + _In_ PKSPROPERTY pProperty, + _Inout_ PVOID pData +) +{ + PAGED_CODE(); + + NT_ASSERT(pIrp); + NT_ASSERT(pProperty); + + CCaptureFilter *pFilter = reinterpret_cast <CCaptureFilter *>(KsGetFilterFromIrp(pIrp)->Context); + PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp); + ULONG ulOutputBufferLength = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength; + ULONG RequiredLength = 0; + + NTSTATUS Status = + pFilter->m_Sensor->GetPfsCaps( nullptr, &RequiredLength ); + + // Note: We may want to determine capabilities at runtime in the future. + + // We only handle GETs + if( NT_SUCCESS(Status) ) + { + if (ulOutputBufferLength == 0) + { + pIrp->IoStatus.Information = RequiredLength; + Status = STATUS_BUFFER_OVERFLOW; + } + else if (ulOutputBufferLength < RequiredLength) + { + Status = STATUS_BUFFER_TOO_SMALL; + } + else if (pData && ulOutputBufferLength >= RequiredLength) + { + Status = + pFilter->m_Sensor->GetPfsCaps( + (KSCAMERA_PERFRAMESETTING_CAP_HEADER *) pData, + &RequiredLength ); + pIrp->IoStatus.Information = RequiredLength; + } + else + { + Status = STATUS_INVALID_PARAMETER; + } + } + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_PERFRAMESETTING_SET +NTSTATUS +CCaptureFilter::GetPerFrameSettings( + _In_ PIRP pIrp, + _In_ PKSPROPERTY pProperty, + _Inout_ PVOID pData +) +{ + PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; + + NT_ASSERT(pIrp); + NT_ASSERT(pProperty); + + CCaptureFilter *pFilter = reinterpret_cast <CCaptureFilter *>(KsGetFilterFromIrp(pIrp)->Context); + PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp); + ULONG ulOutputBufferLength = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength; + ULONG ulOutputSize = + pFilter->m_pPerFrameSettings ? pFilter->m_pPerFrameSettings->Size : 0; + + // Only handle GETs + if (ulOutputBufferLength == 0) + { + pIrp->IoStatus.Information = ulOutputSize; + ntStatus = STATUS_BUFFER_OVERFLOW; + } + else if (ulOutputBufferLength < ulOutputSize) + { + ntStatus = STATUS_BUFFER_TOO_SMALL; + } + else if (pData && ulOutputBufferLength >= ulOutputSize) + { + // Return the cached copy. + RtlCopyMemory( pData, pFilter->m_pPerFrameSettings, ulOutputSize ); + pIrp->IoStatus.Information = ulOutputSize; + ntStatus = STATUS_SUCCESS; + } + else + { + ntStatus = STATUS_INVALID_PARAMETER; + } + + return ntStatus; +} + +// Set KSPROPERTY_CAMERACONTROL_PERFRAMESETTING_SET +NTSTATUS +CCaptureFilter:: +SetPerFrameSettings( + _In_ PIRP pIrp, + _In_ PKSPROPERTY pProperty, + _Inout_ PVOID pData +) +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_SUCCESS; + + NT_ASSERT(pIrp); + NT_ASSERT(pProperty); + + CCaptureFilter *pFilter = reinterpret_cast <CCaptureFilter *>(KsGetFilterFromIrp(pIrp)->Context); + PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp); + ULONG ulOutputBufferLength = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength; + + // Only handle SETs + if (ulOutputBufferLength == 0) + { + // This is pretty meaningless. + // We can't really tell the caller the size of this buffer. + pIrp->IoStatus.Information = + sizeof(KSCAMERA_PERFRAMESETTING_HEADER) + + sizeof(KSCAMERA_PERFRAMESETTING_FRAME_HEADER) + + sizeof(KSCAMERA_PERFRAMESETTING_ITEM_HEADER) ; + Status = STATUS_BUFFER_OVERFLOW; + } + else if (ulOutputBufferLength < sizeof(KSCAMERA_PERFRAMESETTING_HEADER)) + { + Status = STATUS_BUFFER_TOO_SMALL; + } + else + { + PKSCAMERA_PERFRAMESETTING_HEADER pPFS = + (PKSCAMERA_PERFRAMESETTING_HEADER) pData ; + ISP_FRAME_SETTINGS *pSettings = nullptr; + + // Parse, but don't save the PerFrameSettings + Status = pFilter->ParsePFSBuffer( pPFS, ulOutputBufferLength, &pSettings ); + + // Cache a copy of the unparsed PFS for the GET. + // Pass the parsed settings down to the sensor. + if( NT_SUCCESS(Status) ) + { + delete [] ((PBYTE) pFilter->m_pPerFrameSettings); + pFilter->m_pPerFrameSettings = (PKSCAMERA_PERFRAMESETTING_HEADER) + new (PagedPool, '-SFP') BYTE [pPFS->Size]; + + if( pFilter->m_pPerFrameSettings ) + { + // Cache a copy of the settings for the GET. + RtlCopyMemory( pFilter->m_pPerFrameSettings, pPFS, pPFS->Size ); + + // Program the sensor with a copy of the parsed settings. + // The sensor object should copy what it needs. + pFilter->m_Sensor->SetPFS( pSettings, pPFS->FrameCount, pPFS->LoopCount ); + } + else + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + } + + // Delete the settings buffer ParsePFSBuffer created. + delete [] pSettings; + } + + return Status; +} + +// Set KSPROPERTY_CAMERACONTROL_PERFRAMESETTING_CLEAR +NTSTATUS +CCaptureFilter::ClearPerFrameSettings( + _In_ PIRP pIrp, + _In_ PKSPROPERTY pProperty, + _Inout_ PVOID pData +) +{ + PAGED_CODE(); + NTSTATUS ntStatus = STATUS_SUCCESS; + + NT_ASSERT(pIrp); + NT_ASSERT(pProperty); + + CCaptureFilter *pFilter = reinterpret_cast <CCaptureFilter *>(KsGetFilterFromIrp(pIrp)->Context); + + // Only handle SETs + delete [] ((PBYTE) pFilter->m_pPerFrameSettings); + pFilter->m_pPerFrameSettings = nullptr; + pFilter->m_Sensor->SetPFS( nullptr, 0, 0 ); + + return ntStatus; +} + +PKSCAMERA_PERFRAMESETTING_CAP_ITEM_HEADER +Find( + _In_ PKSCAMERA_PERFRAMESETTING_CAP_HEADER Caps, + _In_ ULONG Type +) +/*++ + +Routine Description: + + Helper function that finds a specific PFS capability. + +Arguments: + + Caps - + A list of PFS capabilities. + Type - + The capability type to search for. + +Return Value: + + A pointer to the capability item header. + +--*/ +{ + PAGED_CODE(); + + if( Caps ) + { + PKSCAMERA_PERFRAMESETTING_CAP_ITEM_HEADER Item = + (PKSCAMERA_PERFRAMESETTING_CAP_ITEM_HEADER) (Caps+1); + + for( ULONG i=0; i<Caps->ItemCount; i++ ) + { + if( Item->Type == Type ) + { + return Item; + } + Item = (PKSCAMERA_PERFRAMESETTING_CAP_ITEM_HEADER) (((PBYTE) Item) + Item->Size); + } + } + return nullptr; +} + +// This function can be used to validate PerFrameSettings, or +// it can be used to populate a buffer containing PFS settings. +_Success_(return == 0) +NTSTATUS +CCaptureFilter:: +ParsePFSBuffer( + _In_reads_bytes_(BufferLimit) + PKSCAMERA_PERFRAMESETTING_HEADER pPFS, + _In_ ULONG BufferLimit, + _Outptr_opt_result_maybenull_ + ISP_FRAME_SETTINGS **ppSettings +) +/*++ + +Routine Description: + + Helper function that parses Per-Frame Settings. + + This function validates the API's PerFrameSettings list and optionally + returns an array of ISP_FRAME_SETTINGS for each frame. + + Any returned array of ISP_FRAME_SETTINGS must be deleted by the caller. + +Arguments: + + pPFS - + A variable length list of per frame settings. + BufferLimit - + The maximum amount of space, in bytes, used by the PFS list. + ppSettings - + An optional pointer to an array of frame settings to be populated. + +Return Value: + + Success / failure + +--*/ +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_SUCCESS; + + DBG_ENTER("[%S]()", GetFilterName()); + + NT_ASSERT(pPFS); + NT_ASSERT(BufferLimit!=0); + + if( !pPFS || + BufferLimit == 0 || + pPFS->Size > BufferLimit || + pPFS->Size < sizeof(KSCAMERA_PERFRAMESETTING_HEADER) || + pPFS->LoopCount!=1 || // Hard-coded to 1, per spec. + pPFS->FrameCount > MAX_FRAME_COUNT || + pPFS->FrameCount == 0 ) + { + Status = STATUS_INVALID_PARAMETER; + } + else + { + ULONG i=0 ; + ISP_FRAME_SETTINGS *pSettings = nullptr; + LPVOID pEnd = ((LPBYTE) pPFS) + BufferLimit ; + PKSCAMERA_PERFRAMESETTING_FRAME_HEADER pFrame = + (PKSCAMERA_PERFRAMESETTING_FRAME_HEADER) &pPFS[1]; + + // Make sure we have at least one frame in the array. + ULONG FrameCount = pPFS->FrameCount ? pPFS->FrameCount : 1 ; + + // Query the PFS Caps from the Sensor + PKSCAMERA_PERFRAMESETTING_CAP_HEADER Caps = nullptr; + ULONG RequiredSize = 0; + Status = m_Sensor->GetPfsCaps( nullptr, &RequiredSize ); + + if( NT_SUCCESS(Status) ) + { + Caps = (PKSCAMERA_PERFRAMESETTING_CAP_HEADER) new (PagedPool, '-SFP') BYTE[RequiredSize]; + + if( Caps ) + { + RtlZeroMemory( Caps, RequiredSize ); + Status = m_Sensor->GetPfsCaps( Caps, &RequiredSize ); + } + else + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + } + + if( NT_SUCCESS(Status) ) + { + // Allocate an array + pSettings = new (NonPagedPoolNx, '-SFP') ISP_FRAME_SETTINGS[FrameCount]; + if( !pSettings ) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + else + { + // Initialize the array to our globals + pSettings[0] = *m_Sensor->GetGlobalIspSettings(); + for( i=1; i<FrameCount; i++ ) + { + pSettings[i] = pSettings[0]; + } + + while( ((pFrame+1)<=pEnd) ) + { + PKSCAMERA_PERFRAMESETTING_FRAME_HEADER pNextFrame = + (PKSCAMERA_PERFRAMESETTING_FRAME_HEADER) + (((LPBYTE)pFrame) + pFrame->Size); + PKSCAMERA_PERFRAMESETTING_ITEM_HEADER pItem = + (PKSCAMERA_PERFRAMESETTING_ITEM_HEADER) &pFrame[1]; + + // Verify that the frame is within the buffer. + if( pFrame->Id >= pPFS->FrameCount || + pNextFrame > pEnd || + pFrame->Size < sizeof(KSCAMERA_PERFRAMESETTING_FRAME_HEADER) ) + { + DBG_TRACE( "Malformed PFS Buffer. pPFS=%p pFrame=%p", + pPFS, pFrame ); + + Status=STATUS_INVALID_PARAMETER; + break; + } + + DBG_TRACE("Frame Id=%d",pFrame->Id); + + ISP_FRAME_SETTINGS &FrameSetting = pSettings[pFrame->Id] ; + + // Scan for at most n Items regardless. + for( i=0; + i < pFrame->ItemCount && + (pItem+1) <= (PVOID)pNextFrame; + i++ ) + { + PKSCAMERA_PERFRAMESETTING_ITEM_HEADER pNextItem = + (PKSCAMERA_PERFRAMESETTING_ITEM_HEADER) + (((LPBYTE)pItem) + pItem->Size); + + PKSCAMERA_PERFRAMESETTING_CAP_ITEM_HEADER ItemCap = + Find( Caps, pItem->Type ); + + // Verify that the item is within the frame ... + // ... and a supported capability. + if( pNextItem>(LPVOID)pNextFrame || + pItem->Size<sizeof(KSCAMERA_PERFRAMESETTING_ITEM_HEADER) || + !ItemCap ) + { + Status=STATUS_INVALID_PARAMETER; + break; + } + + switch( pItem->Type ) + { + case KSCAMERA_PERFRAMESETTING_ITEM_EXPOSURE_TIME: + DBG_TRACE("KSCAMERA_PERFRAMESETTING_ITEM_EXPOSURE_TIME"); + + FrameSetting.ExposureMode = + TranslatePFS2VideoProcFlags( pItem->Flags ); + + if( pItem->Flags & KSCAMERA_PERFRAMESETTING_MANUAL ) + { + if( pItem->Size== + sizeof(KSCAMERA_PERFRAMESETTING_ITEM_HEADER)+ + sizeof(KSCAMERA_EXTENDEDPROP_VALUE) ) + { + FrameSetting.ExposureSetting.VideoProc.Value = + ((PKSCAMERA_EXTENDEDPROP_VALUE) &(pItem[1]))->Value; + // Make sure the setting is in range. + Status = + BoundsCheckSigned( + FrameSetting.ExposureSetting.VideoProc.Value.ll, + ((SOC_CAP_WITH_STEPPING_LONGLONG *) ItemCap)->Stepping ); + DBG_TRACE("Status=0x%08X, ExposureMode=KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL, ExposureTime=%lldns, element=%d", + Status, FrameSetting.ExposureSetting.VideoProc.Value.ll, i); + } + else + { + Status=STATUS_INVALID_PARAMETER; + DBG_TRACE("Status=STATUS_INVALID_PARAMETER"); + } + } + else if( pItem->Size!=sizeof(KSCAMERA_PERFRAMESETTING_ITEM_HEADER) ) + { + Status=STATUS_INVALID_PARAMETER; + DBG_TRACE("Status=STATUS_INVALID_PARAMETER"); + } + break; + + case KSCAMERA_PERFRAMESETTING_ITEM_FLASH: + DBG_TRACE("KSCAMERA_PERFRAMESETTING_ITEM_FLASH"); + FrameSetting.FlashMode = pItem->Flags; + if( pItem->Flags & + (KSCAMERA_EXTENDEDPROP_FLASH_ON_ADJUSTABLEPOWER | + KSCAMERA_EXTENDEDPROP_FLASH_AUTO_ADJUSTABLEPOWER) ) + { + if( pItem->Size== + sizeof(KSCAMERA_PERFRAMESETTING_ITEM_HEADER)+ + sizeof(KSCAMERA_EXTENDEDPROP_VALUE) ) + { + FrameSetting.FlashValue = + ((PKSCAMERA_EXTENDEDPROP_VALUE) &(pItem[1]))->Value.ul; + + // Make sure the setting is in range. + if( FrameSetting.FlashValue > 100 ) + { + Status=STATUS_INVALID_PARAMETER; + } + else + { + DBG_TRACE("FlashPower (%d%) accepted...", FrameSetting.FlashValue); + } + } + else + { + Status=STATUS_INVALID_PARAMETER; + } + } + else if( pItem->Size!=sizeof(KSCAMERA_PERFRAMESETTING_ITEM_HEADER) ) + { + Status=STATUS_INVALID_PARAMETER; + } + + if( NT_SUCCESS(Status) ) + { + DBG_TRACE("FlashMode=0x%016llX, FlashPower=%d", FrameSetting.FlashMode, FrameSetting.FlashValue); + } + break; + + case KSCAMERA_PERFRAMESETTING_ITEM_EXPOSURE_COMPENSATION: + DBG_TRACE("KSCAMERA_PERFRAMESETTING_ITEM_EXPOSURE_COMPENSATION"); + { + LONG Denominator = EVFlags2Denominator( pItem->Flags ); + KSPROPERTY_STEPPING_LONG + Bounds = ((SOC_CAP_WITH_STEPPING *) ItemCap)->Stepping; + + // Adjust the bounds for the step size... (A quirk of EV) + Bounds.Bounds.SignedMinimum *= Denominator; + Bounds.Bounds.SignedMaximum *= Denominator; + + FrameSetting.EVCompensation.Mode = (ULONG) + pItem->Flags & ~(KSCAMERA_PERFRAMESETTING_AUTO); + + // Validate manual setting + if( (pItem->Flags != KSCAMERA_PERFRAMESETTING_AUTO) ) + { + if( pItem->Size== + sizeof(KSCAMERA_PERFRAMESETTING_ITEM_HEADER)+ + sizeof(KSCAMERA_EXTENDEDPROP_VALUE) && + (Denominator != 0) ) + { + FrameSetting.EVCompensation.Value = + ((PKSCAMERA_EXTENDEDPROP_VALUE) &(pItem[1]))->Value.l; + + // Make sure the setting is in range. + Status = + BoundsCheckSigned( + FrameSetting.EVCompensation.Value, + Bounds ); + } + else + { + Status=STATUS_INVALID_PARAMETER; + } + } + // Auto can be the only flag, if auto is enabled. + else //if( pItem->Flags == KSCAMERA_PERFRAMESETTING_AUTO ) + { + if( pItem->Size==sizeof(KSCAMERA_PERFRAMESETTING_ITEM_HEADER) ) + { + static + ULONG step[] = + { + 0, + KSCAMERA_EXTENDEDPROP_EVCOMP_FULLSTEP, //1 + KSCAMERA_EXTENDEDPROP_EVCOMP_HALFSTEP, //2 + KSCAMERA_EXTENDEDPROP_EVCOMP_THIRDSTEP, //3 + KSCAMERA_EXTENDEDPROP_EVCOMP_QUARTERSTEP, //4 + 0, //5 + KSCAMERA_EXTENDEDPROP_EVCOMP_SIXTHSTEP //6 + }; + + // Work back from the randomly selected denominator ... + /// ... to the step flag. + FrameSetting.EVCompensation.Mode = step[Denominator]; + + // Now pick a "random" numerator that is in range. + FrameSetting.EVCompensation.Value = (LONG) + GetRandom( Bounds.Bounds.SignedMinimum, + Bounds.Bounds.SignedMaximum ); + } + else + { + Status=STATUS_INVALID_PARAMETER; + } + } + } + break; + + case KSCAMERA_PERFRAMESETTING_ITEM_ISO: + DBG_TRACE("KSCAMERA_PERFRAMESETTING_ITEM_ISO: Flags=0x%016llX", pItem->Flags); + + FrameSetting.ISOMode = pItem->Flags; + // Handle Auto. + if( pItem->Flags == KSCAMERA_EXTENDEDPROP_ISO_AUTO ) + { + if( pItem->Size==sizeof(KSCAMERA_PERFRAMESETTING_ITEM_HEADER) ) + { + FrameSetting.ISOValue = 0; + } + else + { + Status=STATUS_INVALID_PARAMETER; + } + } + // Handle manual settings. + else if( pItem->Flags == KSCAMERA_EXTENDEDPROP_ISO_MANUAL ) + { + if( pItem->Size== + sizeof(KSCAMERA_PERFRAMESETTING_ITEM_HEADER)+ + sizeof(KSCAMERA_EXTENDEDPROP_VALUE) ) + { + FrameSetting.ISOValue = + ((PKSCAMERA_EXTENDEDPROP_VALUE) &(pItem[1]))->Value.ul; + // Make sure the setting is in range. + Status = + BoundsCheckUnsigned( + FrameSetting.ISOValue, + ((SOC_CAP_WITH_STEPPING *)ItemCap)->Stepping ); + + DBG_TRACE("ISOValue=%d", FrameSetting.ISOValue); + } + else + { + Status=STATUS_INVALID_PARAMETER; + } + } + else + { + Status=STATUS_INVALID_PARAMETER; + } + break; + + case KSCAMERA_PERFRAMESETTING_ITEM_FOCUS: + DBG_TRACE("KSCAMERA_PERFRAMESETTING_ITEM_FOCUS"); + if( pItem->Flags == KSCAMERA_PERFRAMESETTING_MANUAL ) + { + if( pItem->Size== + sizeof(KSCAMERA_PERFRAMESETTING_ITEM_HEADER)+ + sizeof(KSCAMERA_EXTENDEDPROP_VALUE) ) + { + FrameSetting.FocusMode = + KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL; + FrameSetting.FocusSetting.VideoProc = + *((PKSCAMERA_EXTENDEDPROP_VALUE) &(pItem[1])); + // Make sure the setting is in range. + Status = + BoundsCheckUnsigned( + FrameSetting.FocusSetting.VideoProc.Value.ul, + ((SOC_CAP_WITH_STEPPING *)ItemCap)->Stepping ); + } + else + { + Status=STATUS_INVALID_PARAMETER; + } + } + else + { + Status=STATUS_INVALID_PARAMETER; + } + break; + + case KSCAMERA_PERFRAMESETTING_ITEM_PHOTOCONFIRMATION: + DBG_TRACE("KSCAMERA_PERFRAMESETTING_ITEM_PHOTOCONFIRMATION"); + + if( pItem->Size!=sizeof(KSCAMERA_PERFRAMESETTING_ITEM_HEADER) ) + { + Status=STATUS_INVALID_PARAMETER; + } + else + { + switch( pItem->Flags ) + { + case KSCAMERA_EXTENDEDPROP_PHOTOCONFIRMATION_ON: + FrameSetting.bPhotoConfirmation = TRUE; + DBG_TRACE("PFS Photo Confirmation ON for frame #%d", pFrame->Id); + break; + + case KSCAMERA_EXTENDEDPROP_PHOTOCONFIRMATION_OFF: + FrameSetting.bPhotoConfirmation = FALSE; + DBG_TRACE("PFS Photo Confirmation OFF for frame #%d", pFrame->Id); + break; + + default: + Status=STATUS_INVALID_PARAMETER; + break; + } + } + break; + + case KSCAMERA_PERFRAMESETTING_ITEM_CUSTOM: + DBG_TRACE("KSCAMERA_PERFRAMESETTING_ITEM_CUSTOM"); + break; + + default: + // We don't understand this item. Do nothing. + NT_ASSERT(FALSE); + break; + } + + // Bail here (a little early) if any of the parsing failed. + if( !NT_SUCCESS(Status) ) + { + break; + } + + // Move to the next Item + pItem = pNextItem; + } + + // Bail here (a little early) if any of the parsing failed. + if( !NT_SUCCESS(Status) ) + { + DBG_TRACE( "Malformed PFS Buffer. pPFS=%p pItem=%p", + pPFS, pItem ); + break; + } + + // Move to next Frame + pFrame = pNextFrame; + } + + // We need to log where in the buffer we encountered an error. + // For now we just emit info to the debugger. + } + + if( NT_SUCCESS(Status) && ppSettings ) + { + *ppSettings = pSettings; + } + else + { + delete [] pSettings; + } + } + + delete [] ((PBYTE) Caps); + } + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_EXTENDED_FOCUSSTATE +NTSTATUS +CCaptureFilter::GetFocusState( + _Inout_ CExtendedProperty *pState +) +{ + PAGED_CODE(); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pState->isValid() && + pState->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE ) + { + KSCAMERA_EXTENDEDPROP_FOCUSSTATE FocusState = KSCAMERA_EXTENDEDPROP_FOCUSSTATE_UNINITIALIZED; + Status = m_Sensor->GetFocusState( &FocusState ); + if( NT_SUCCESS(Status) ) + { + *pState = CExtendedProperty( (ULONGLONG) FocusState ); + pState->Capability = 0; + } + } + DBG_LEAVE("(PinId=%u, Flags=0x%016llX, Version=%u)=0x%08X", + pState->PinId, pState->Flags, pState->Version, Status); + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_EXTENDED_FOCUSPRIORITY +NTSTATUS +CCaptureFilter:: +GetFocusPriority( + _Inout_ CExtendedProperty *pPriority +) +{ + PAGED_CODE(); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pPriority->isValid() && + pPriority->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE ) + { + Status = m_Sensor->GetFocusPriority( pPriority ); + } + DBG_LEAVE("(PinId=%u, Flags=0x%016llX, Version=%u)=0x%08X", + pPriority->PinId, pPriority->Flags, pPriority->Version, Status); + return Status; +} + +// Set KSPROPERTY_CAMERACONTROL_EXTENDED_FOCUSPRIORITY +NTSTATUS +CCaptureFilter:: +SetFocusPriority( + _In_ CExtendedProperty *pPriority +) +{ + PAGED_CODE(); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pPriority->isValid() && + pPriority->Capability == 0 && + pPriority->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE && + (pPriority->Flags & ~KSCAMERA_EXTENDEDPROP_FOCUSPRIORITY_ON) == 0 ) + { + Status = m_Sensor->SetFocusPriority( pPriority ); + } + DBG_LEAVE("(PinId=%u, Flags=0x%016llX, Version=%u)=0x%08X", + pPriority->PinId, pPriority->Flags, pPriority->Version, Status); + return Status; +} + +// KSPROPERTY_CAMERACONTROL_EXTENDED_ROI_CONFIGCAPS Get handler +NTSTATUS +CCaptureFilter:: +GetRoiConfigCaps( + _Inout_ CRoiConfig *pOutput +) +{ + PAGED_CODE(); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pOutput->isValid() && + pOutput->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE ) + { + Status = m_Sensor->GetRoiConfigCaps( pOutput ); + } + return Status; +} + +// KSPROPERTY_CAMERACONTROL_EXTENDED_ROI_ISPCONTROL Get handler +// +// Note: ROI handlers are left as static member functions because +// it wasn't worth the code needed to generalize handling of a +// variable length parameter. +NTSTATUS +CCaptureFilter:: +GetRoiIspControl( + _In_ PIRP pIrp, + _In_ PKSPROPERTY pProperty, + _Inout_ PVOID pData +) +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + DBG_ENTER("()"); + + NT_ASSERT(pIrp); + NT_ASSERT(pProperty); + + CCaptureFilter *pFilter = reinterpret_cast <CCaptureFilter *>(KsGetFilterFromIrp(pIrp)->Context); + CSensor *pSensor = pFilter->m_Sensor; + PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp); + ULONG ulOutputBufferLength = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength; + CRoiProperty *pRoi = (reinterpret_cast<CRoiProperty *>(pData)); + ULONG RequiredSize = pSensor->SizeOfRoi(); + + // Only handle GETs + if( ulOutputBufferLength == 0 ) + { + pIrp->IoStatus.Information = RequiredSize;; + Status = STATUS_BUFFER_OVERFLOW; + } + else if( ulOutputBufferLength < RequiredSize ) + { + Status = STATUS_BUFFER_TOO_SMALL; + } + else if( pData ) + { + Status = pSensor->GetRoi( pRoi ); + if( NT_SUCCESS(Status) ) + { + pIrp->IoStatus.Information = pRoi->GetSize(); + } + } + + DBG_LEAVE("()=0x%08X",Status); + return Status; +} + +// KSPROPERTY_CAMERACONTROL_EXTENDED_ROI_ISPCONTROL Set handler +NTSTATUS +CCaptureFilter:: +SetRoiIspControl( + _In_ PIRP pIrp, + _In_ PKSPROPERTY pProperty, + _Inout_ PVOID pData +) +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + DBG_ENTER("()"); + NT_ASSERT(pIrp); + NT_ASSERT(pProperty); + + CCaptureFilter *pFilter = reinterpret_cast <CCaptureFilter *>(KsGetFilterFromIrp(pIrp)->Context); + CSensor *pSensor = pFilter->m_Sensor; + PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp); + ULONG ulOutputBufferLength = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength; + CRoiProperty *pRoi = (reinterpret_cast<CRoiProperty *>(pData)); + ULONG RequiredSize = sizeof(*pRoi); + + // Only handle SETs + if( ulOutputBufferLength == 0 ) + { + // Minimum size for this control. + pIrp->IoStatus.Information = RequiredSize; + Status = STATUS_BUFFER_OVERFLOW; + } + else if( ulOutputBufferLength < RequiredSize ) + { + DBG_TRACE("***BUFFER TOO SMALL*** ulOutputBufferLength=%d, Size=%d", + ulOutputBufferLength, pRoi->Size ); + Status = STATUS_BUFFER_TOO_SMALL; + } + else if( pData && ulOutputBufferLength >= pRoi->Size ) + { + // Validate the data blob. + if( pRoi->isValid() && + pRoi->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE && + pRoi->Flags == 0 ) + { + Status = INVOKE_SET_ASYNC( pSensor, Roi, pRoi, pFilter->m_RoiNotifier ); + } + } + + DBG_LEAVE("()=0x%08X",Status); + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_EXTENDED_ISO_ADVANCED. +NTSTATUS +CCaptureFilter:: +GetIsoAdvanced( + _Inout_ CExtendedVidProcSetting *pIso +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pIso->isValid() && + m_Sensor->IsStillIndex(pIso->PinId) ) + { + Status = m_Sensor->GetIsoAdvanced( pIso ); + } + + // Report to the debug output... + DBG_TRACE(" Flags = 0x%016llX", pIso->Flags); + DBG_TRACE(" Min = %d", pIso->m_Setting.Min); + DBG_TRACE(" Max = %d", pIso->m_Setting.Max); + DBG_TRACE(" Step = %d", pIso->m_Setting.Step); + DBG_TRACE("VideoProc.Value = %lld", pIso->m_Setting.VideoProc.Value.ll); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Set KSPROPERTY_CAMERACONTROL_EXTENDED_ISO_ADVANCED. +NTSTATUS +CCaptureFilter:: +SetIsoAdvanced( + _In_ CExtendedVidProcSetting *pIso +) +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + DBG_ENTER("()"); + + // Report to the debug output... + DBG_TRACE(" Flags = 0x%016llX", pIso->Flags); + DBG_TRACE(" Min = %d", pIso->m_Setting.Min); + DBG_TRACE(" Max = %d", pIso->m_Setting.Max); + DBG_TRACE(" Step = %d", pIso->m_Setting.Step); + DBG_TRACE("VideoProc.Value = %lld", pIso->m_Setting.VideoProc.Value.ll); + + // Validate + switch( pIso->Flags ) + { + case KSCAMERA_EXTENDEDPROP_ISO_AUTO: + case KSCAMERA_EXTENDEDPROP_FLAG_CANCELOPERATION: + case KSCAMERA_EXTENDEDPROP_ISO_AUTO | KSCAMERA_EXTENDEDPROP_FLAG_CANCELOPERATION: + case KSCAMERA_EXTENDEDPROP_ISO_MANUAL: + case KSCAMERA_EXTENDEDPROP_ISO_MANUAL | KSCAMERA_EXTENDEDPROP_FLAG_CANCELOPERATION: + if( pIso->isValid() && + (pIso->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) && + m_Sensor->IsStillIndex(pIso->PinId) ) + { + CExtendedVidProcSetting Caps; + Status = m_Sensor->GetIsoAdvanced(&Caps); + + if( NT_SUCCESS(Status) ) + { + // Just save the parameters + if( pIso->Flags & KSCAMERA_EXTENDEDPROP_ISO_MANUAL ) + { + Status = BoundsCheckSigned( pIso->GetLONGLONG(), Caps.m_Setting ); + } + if( NT_SUCCESS(Status) ) + { + Status = INVOKE_SET_ASYNC( m_Sensor, IsoAdvanced, pIso, m_IsoAdvancedNotifier ) + } + } + else + { + Status = STATUS_INVALID_PARAMETER; + } + } + break; + } + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_EXTENDED_VFR. +NTSTATUS +CCaptureFilter:: +GetVFR( + _Inout_ CExtendedProperty *pVFR +) +{ + PAGED_CODE(); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( m_Sensor->IsVideoIndex(pVFR->PinId) && + pVFR->isValid() ) + { + //Get the current VFR state + Status = m_Sensor->GetVFR( pVFR ); + } + DBG_LEAVE("PinId=%u, VideoIndex=%u, Flags=0x%016llX, Version=%u, Status=0x%08X", + pVFR->PinId, m_Sensor->GetNextVideoIndex(), pVFR->Flags, pVFR->Version, Status); + return Status; +} + +// Set KSPROPERTY_CAMERACONTROL_EXTENDED_VFR. +NTSTATUS +CCaptureFilter:: +SetVFR( + _In_ CExtendedProperty *pVFR +) +{ + PAGED_CODE(); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( m_Sensor->IsVideoIndex(pVFR->PinId) && + pVFR->isValid() && + pVFR->Capability == 0 && + (KSCAMERA_EXTENDEDPROP_VFR_OFF == pVFR->Flags || + KSCAMERA_EXTENDEDPROP_VFR_ON == pVFR->Flags || + KSCAMERA_EXTENDEDPROP_VIDEOHDR_AUTO == pVFR->Flags ) ) + { + //Set the current VFR state + Status = m_Sensor->SetVFR( pVFR ); + } + DBG_LEAVE("PinId=%u, VideoIndex=%u, Flags=0x%016llX, Version=%u, Status=0x%08X", + pVFR->PinId, m_Sensor->GetNextVideoIndex(), pVFR->Flags, pVFR->Version, Status); + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_EXTENDED_VIDEOHDR. +NTSTATUS +CCaptureFilter:: +GetVideoHDR( + _Inout_ CExtendedProperty *pVideoHDR +) +{ + PAGED_CODE(); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( m_Sensor->IsVideoIndex(pVideoHDR->PinId) && + pVideoHDR->isValid() ) + { + //Get the current Video HDR state + Status = m_Sensor->GetVideoHDR(pVideoHDR); + } + DBG_LEAVE("PinId=%u, VideoIndex=%u, Flags=0x%016llX, Version=%u, Status=0x%08X", + pVideoHDR->PinId, m_Sensor->GetNextVideoIndex(), pVideoHDR->Flags, pVideoHDR->Version, Status); + return Status; +} + +// Set KSPROPERTY_CAMERACONTROL_EXTENDED_VIDEOHDR. +NTSTATUS +CCaptureFilter:: +SetVideoHDR( + _In_ CExtendedProperty *pVideoHDR +) +{ + PAGED_CODE(); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + // Call must come for Video PIN only and flags must be supported and mutually exclusive and version must be 1 + if( m_Sensor->IsVideoIndex(pVideoHDR->PinId) && + pVideoHDR->isValid() && + !(pVideoHDR->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) && + (KSCAMERA_EXTENDEDPROP_VIDEOHDR_OFF == pVideoHDR->Flags || + KSCAMERA_EXTENDEDPROP_VIDEOHDR_ON == pVideoHDR->Flags || + KSCAMERA_EXTENDEDPROP_VIDEOHDR_AUTO== pVideoHDR->Flags) ) + { + if( !m_pinArray[pVideoHDR->PinId] || + m_pinArray[pVideoHDR->PinId]->GetState() == PinStopped ) + { + CExtendedProperty Caps(*pVideoHDR); + Status = m_Sensor->GetVideoHDR( &Caps ); + + if( NT_SUCCESS(Status) ) + { + // Assume an invalid parameter. + Status = STATUS_INVALID_PARAMETER; + + // Call must come for Video PIN only and flags must be supported and mutually exclusive and version must be 1 + if( pVideoHDR->Flags == (pVideoHDR->Flags & Caps.Capability) ) + { + Status = m_Sensor->SetVideoHDR(pVideoHDR); + } + } + } + else + { + Status = STATUS_INVALID_DEVICE_STATE; + } + } + + DBG_LEAVE("PinId=%u, VideoIndex=%u, Flags=0x%016llX, Version=%u, Status=0x%08X", + pVideoHDR->PinId, m_Sensor->GetNextVideoIndex(), pVideoHDR->Flags, pVideoHDR->Version, Status); + return Status; +} + + +// Get KSPROPERTY_CAMERACONTROL_EXTENDED_HISTOGRAM. +NTSTATUS +CCaptureFilter:: +GetHistogram( + _Inout_ CExtendedProperty *pHistogram +) +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( m_Sensor->IsPreviewIndex(pHistogram->PinId) && + pHistogram->isValid() && + pHistogram->Capability == 0 ) + { + //Get the histogram state + Status = m_Sensor->GetHistogram( pHistogram ); + } + DBG_TRACE("pHistogram->PinId = %u, m_sensor->PreviewIndex = %u, pHistogram->Flags = %016llx, pHistogram->Version = %u", + pHistogram->PinId, m_Sensor->GetNextPreviewIndex(), pHistogram->Flags, pHistogram->Version); + return Status; +} + +// Set KSPROPERTY_CAMERACONTROL_EXTENDED_HISTOGRAM. +NTSTATUS +CCaptureFilter:: +SetHistogram( + _In_ CExtendedProperty *pHistogram +) +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( m_Sensor->IsPreviewIndex(pHistogram->PinId) && + pHistogram->isValid() && + !(pHistogram->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) && + (KSCAMERA_EXTENDEDPROP_HISTOGRAM_OFF == pHistogram->Flags || + KSCAMERA_EXTENDEDPROP_HISTOGRAM_ON == pHistogram->Flags ) ) + { + if( m_pinArray[pHistogram->PinId] && + m_pinArray[pHistogram->PinId]->GetState() != PinStopped ) + { + Status = STATUS_INVALID_DEVICE_STATE; + } + else + { + //Set the histogram state. + Status = m_Sensor->SetHistogram( pHistogram ); + } + } + + DBG_TRACE("pHistogram->PinId = %u, m_sensor->PreviewIndex = %u, pHistogram->Flags = %016llx, pHistogram->Version = %u", + pHistogram->PinId, m_Sensor->GetNextPreviewIndex(), pHistogram->Flags, pHistogram->Version); + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_EXTENDED_FACEDETECTION. +NTSTATUS +CCaptureFilter:: +GetFaceDetection( + _Inout_ CExtendedVidProcSetting *pFaceDetect +) +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + DBG_ENTER("()"); + + if( pFaceDetect->PinId==KSCAMERA_EXTENDEDPROP_FILTERSCOPE && + pFaceDetect->isValid() ) + { + //Get the FaceDetection state + Status = m_Sensor->GetFaceDetection( pFaceDetect ); + } + + DBG_LEAVE("(): PinId=0x%08X, Flags=0x%016llX, Version=%u, Value=%d, Status=0x%08X", + pFaceDetect->PinId, pFaceDetect->Flags, pFaceDetect->Version, pFaceDetect->GetULONG(), Status); + return Status; +} + +// Set KSPROPERTY_CAMERACONTROL_EXTENDED_FACEDETECTION. +NTSTATUS +CCaptureFilter:: +SetFaceDetection( + _In_ CExtendedVidProcSetting *pFaceDetect +) +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + DBG_ENTER("(): PinId=0x%08X, Flags=0x%016llX, Version=%u, Value=%d", + pFaceDetect->PinId, pFaceDetect->Flags, pFaceDetect->Version, pFaceDetect->GetULONG()); + + if( pFaceDetect->PinId==KSCAMERA_EXTENDEDPROP_FILTERSCOPE && + pFaceDetect->isValid() && + ( KSCAMERA_EXTENDEDPROP_FACEDETECTION_OFF == pFaceDetect->Flags || + (KSCAMERA_EXTENDEDPROP_FACEDETECTION_MASK & pFaceDetect->Flags) !=0 ) ) + { + CExtendedVidProcSetting Caps(*pFaceDetect); + Status = m_Sensor->GetFaceDetection( &Caps ); + + if( NT_SUCCESS(Status) ) + { + // Assume an invalid parameter. + Status = STATUS_INVALID_PARAMETER; + + if( pFaceDetect->Flags == (pFaceDetect->Flags & Caps.Capability) && + ( KSCAMERA_EXTENDEDPROP_FACEDETECTION_OFF == pFaceDetect->Flags || + NT_SUCCESS( Status = Caps.BoundsCheck( pFaceDetect->GetULONG() ) ) ) ) + { + //Set the FaceDetection state. + Status = m_Sensor->SetFaceDetection( pFaceDetect ); + } + } + } + + DBG_LEAVE("(): Status=0x%08X", Status); + return Status; +} + +// KSPROPERTY_CAMERACONTROL_EXTENDED_ZOOM Get handler +NTSTATUS +CCaptureFilter:: +GetZoom( + _Inout_ CExtendedVidProcSetting *pZoom +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pZoom->isValid() && + pZoom->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE ) + { + Status = m_Sensor->GetZoom(pZoom); + } + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// KSPROPERTY_CAMERACONTROL_EXTENDED_ZOOM Set handler +NTSTATUS +CCaptureFilter:: +SetZoom( + _In_ CExtendedVidProcSetting *pZoom +) +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + DBG_ENTER("()"); + + // Validate + if( pZoom->isValid() && + pZoom->PinId == KSCAMERA_EXTENDEDPROP_FILTERSCOPE && + !(pZoom->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) ) + { + CExtendedVidProcSetting Caps(*pZoom); + Status = m_Sensor->GetZoom( &Caps ); + + if( NT_SUCCESS(Status) ) + { + // Report to the debug output... + DBG_TRACE(" Flags = 0x%016llX", Caps.Flags); + DBG_TRACE(" Min = %d", Caps.Min()); + DBG_TRACE(" Max = %d", Caps.Max()); + DBG_TRACE(" Step = %d", Caps.Step()); + DBG_TRACE("VideoProc.Value = %d", pZoom->GetLONG()); + + if( pZoom->Flags == (pZoom->Flags & Caps.Capability) ) + { + Status = BoundsCheckSigned( pZoom->GetLONG(), Caps.m_Setting ); + + if (NT_SUCCESS(Status)) + { + Status = m_Sensor->SetZoom(pZoom); + } + } + else + { + Status = STATUS_INVALID_PARAMETER; + } + } + } + + DBG_LEAVE("(PinId = %u, Flags = 0x%016llX, Caps = 0x%016llX)=0x%08X", + pZoom->PinId, pZoom->Flags, pZoom->Capability, Status); + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_EXTENDED_VIDEOSTABILIZATION. +NTSTATUS +CCaptureFilter:: +GetVideoStabilization( + _Inout_ CExtendedProperty *pVideoStab +) +{ + PAGED_CODE(); + + if (m_Sensor->IsVideoIndex(pVideoStab->PinId) && + pVideoStab->isValid()) + { + //Get the current state + return m_Sensor->GetVideoStabilization(pVideoStab); + } + return STATUS_INVALID_PARAMETER; +} + +// Set KSPROPERTY_CAMERACONTROL_EXTENDED_VIDEOSTABILIZATION. +NTSTATUS +CCaptureFilter:: +SetVideoStabilization( + _In_ CExtendedProperty *pVideoStab +) +{ + PAGED_CODE(); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + // Call must come for Video PIN only and flags must be supported and mutually exclusive and version must be 1 + if( m_Sensor->IsVideoIndex(pVideoStab->PinId) && + pVideoStab->isValid() && + !(pVideoStab->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) && + (KSCAMERA_EXTENDEDPROP_VIDEOSTABILIZATION_OFF == pVideoStab->Flags || + KSCAMERA_EXTENDEDPROP_VIDEOSTABILIZATION_ON == pVideoStab->Flags || + KSCAMERA_EXTENDEDPROP_VIDEOSTABILIZATION_AUTO == pVideoStab->Flags) ) + { + CExtendedProperty Caps(*pVideoStab); + Status = m_Sensor->GetVideoStabilization( &Caps ); + + if( NT_SUCCESS(Status) ) + { + // Assume an invalid parameter. + Status = STATUS_INVALID_PARAMETER; + + // Call must come for Video PIN only and flags must be supported and mutually exclusive and version must be 1 + if( pVideoStab->Flags == (pVideoStab->Flags & Caps.Capability) ) + { + LockFilter Lock(m_pKSFilter); + + if( m_pinArray[pVideoStab->PinId] && + m_pinArray[pVideoStab->PinId]->GetState() != PinStopped ) + { + Status = STATUS_INVALID_DEVICE_STATE; + } + else + { + Status = m_Sensor->SetVideoStabilization(pVideoStab); + } + } + } + } + DBG_TRACE("pVideoStab = %p, PinId = %u, m_sensor->VideoIndex = %u, Flags = %llu, Version = %u", + pVideoStab, pVideoStab->PinId, m_Sensor->GetNextVideoIndex(), pVideoStab->Flags, pVideoStab->Version); + + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_EXTENDED_OIS. +NTSTATUS +CCaptureFilter:: +GetOpticalImageStabilization( + _Inout_ CExtendedProperty *pOIS +) +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( pOIS->PinId==KSCAMERA_EXTENDEDPROP_FILTERSCOPE && + pOIS->isValid() ) + { + //Get the current state + Status = m_Sensor->GetOpticalImageStabilization(pOIS); + } + + DBG_TRACE("pOIS = %p, PinId = %u, Flags = %llu, Version = %u", + pOIS, pOIS->PinId, pOIS->Flags, pOIS->Version); + + return Status; +} + +// Set KSPROPERTY_CAMERACONTROL_EXTENDED_OIS. +NTSTATUS +CCaptureFilter:: +SetOpticalImageStabilization( + _In_ CExtendedProperty *pOIS +) +{ + PAGED_CODE(); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + // Call must come for Video PIN only and flags must be supported and mutually exclusive and version must be 1 + if( pOIS->PinId==KSCAMERA_EXTENDEDPROP_FILTERSCOPE && + pOIS->isValid() && + !(pOIS->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) && + (KSCAMERA_EXTENDEDPROP_OIS_OFF == pOIS->Flags || + KSCAMERA_EXTENDEDPROP_OIS_ON == pOIS->Flags || + KSCAMERA_EXTENDEDPROP_OIS_AUTO== pOIS->Flags)) + { + CExtendedProperty Caps(*pOIS); + Status = m_Sensor->GetOpticalImageStabilization(&Caps); + + if( NT_SUCCESS(Status) ) + { + // Assume an invalid parameter. + Status = STATUS_INVALID_PARAMETER; + + if( pOIS->Flags == (pOIS->Flags & Caps.Capability) ) + { + Status = m_Sensor->SetOpticalImageStabilization(pOIS); + } + } + } + DBG_TRACE("pOIS = %p, PinId = %u, Flags = %llu, Version = %u", + pOIS, pOIS->PinId, pOIS->Flags, pOIS->Version); + + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_EXTENDED_ADVANCEDPHOTO. +NTSTATUS +CCaptureFilter:: +GetAdvancedPhoto( + _Inout_ CExtendedProperty *pAdvancedPhoto +) +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( m_Sensor->IsStillIndex(pAdvancedPhoto->PinId) && + pAdvancedPhoto->isValid() ) + { + //Get the current state + Status = m_Sensor->GetAdvancedPhoto(pAdvancedPhoto); + } + + DBG_LEAVE(" PinId=%u, Flags=0x%016llX, Version=%u, Status=0x%08X", + pAdvancedPhoto->PinId, pAdvancedPhoto->Flags, pAdvancedPhoto->Version, Status); + return Status; +} + +// Set KSPROPERTY_CAMERACONTROL_EXTENDED_ADVANCEDPHOTO. +NTSTATUS +CCaptureFilter:: +SetAdvancedPhoto( + _In_ CExtendedProperty *pAdvancedPhoto +) +{ + PAGED_CODE(); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + // Valid request, still pin & no unsupported flags. + if( m_Sensor->IsStillIndex(pAdvancedPhoto->PinId) && + pAdvancedPhoto->isValid() && + !(pAdvancedPhoto->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) ) + { + CExtendedProperty Caps(*pAdvancedPhoto); + Status = m_Sensor->GetAdvancedPhoto(&Caps); + + if( NT_SUCCESS(Status) ) + { + // Assume an invalid parameter. + Status = STATUS_INVALID_PARAMETER; + + if( pAdvancedPhoto->Flags == (pAdvancedPhoto->Flags & Caps.Capability) ) + { + // Make sure the requested flags are a valid capability combination. + switch( pAdvancedPhoto->Flags ) + { + case KSCAMERA_EXTENDEDPROP_ADVANCEDPHOTO_OFF : + case KSCAMERA_EXTENDEDPROP_ADVANCEDPHOTO_AUTO : + case KSCAMERA_EXTENDEDPROP_ADVANCEDPHOTO_HDR : + case KSCAMERA_EXTENDEDPROP_ADVANCEDPHOTO_FNF : + case KSCAMERA_EXTENDEDPROP_ADVANCEDPHOTO_ULTRALOWLIGHT: + case KSCAMERA_EXTENDEDPROP_ADVANCEDPHOTO_AUTO | + KSCAMERA_EXTENDEDPROP_ADVANCEDPHOTO_HDR : + case KSCAMERA_EXTENDEDPROP_ADVANCEDPHOTO_AUTO | + KSCAMERA_EXTENDEDPROP_ADVANCEDPHOTO_FNF : + case KSCAMERA_EXTENDEDPROP_ADVANCEDPHOTO_AUTO | + KSCAMERA_EXTENDEDPROP_ADVANCEDPHOTO_ULTRALOWLIGHT: + Status = m_Sensor->SetAdvancedPhoto(pAdvancedPhoto); + } + } + } + } + + DBG_LEAVE(" PinId=%u, Flags=0x%016llX, Version=%u, Status=0x%08X", + pAdvancedPhoto->PinId, pAdvancedPhoto->Flags, pAdvancedPhoto->Version, Status); + return Status; +} + +// Get [legacy] KSPROPERTY_CAMERACONTROL_EXPOSURE +NTSTATUS +CCaptureFilter:: +GetCameraProfile( + _Inout_ CExtendedProfile *pProfile +) +{ + PAGED_CODE(); + NTSTATUS Status = STATUS_SUCCESS; + + pProfile->Version = KSCAMERA_EXTENDEDPROP_VERSION; + pProfile->PinId = KSCAMERA_EXTENDEDPROP_FILTERSCOPE; + pProfile->Size = sizeof(KSCAMERA_EXTENDEDPROP_HEADER) + sizeof (KSCAMERA_EXTENDEDPROP_PROFILE); + pProfile->Result = 0; + pProfile->Flags = 0; + pProfile->Capability = KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL; + pProfile->m_Profile = m_Profile; + + return Status; +} + +// Set KSPROPERTY_CAMERACONTROL_EXTENDED_PROFILE. +NTSTATUS +CCaptureFilter:: +SetCameraProfile( + _In_ CExtendedProfile *pProfile +) +{ + PAGED_CODE(); + + if (pProfile->PinId != KSCAMERA_EXTENDEDPROP_FILTERSCOPE || + !pProfile->isValid() || + 0 == (pProfile->Capability & KSCAMERA_EXTENDEDPROP_CAPS_ASYNCCONTROL) || + pProfile->Flags != 0) + { + return STATUS_INVALID_PARAMETER; + } + m_Profile = pProfile->m_Profile; + + m_ProfileNotifier.Set(); + return STATUS_SUCCESS; +} + + +NTSTATUS +CCaptureFilter:: +GetExposure( + _Inout_ KSPROPERTY_CAMERACONTROL_S *pProperty +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = m_Sensor->GetExposure(pProperty); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Set [legacy] KSPROPERTY_CAMERACONTROL_EXPOSURE +NTSTATUS +CCaptureFilter:: +SetExposure( + _In_ KSPROPERTY_CAMERACONTROL_S *pProperty +) +{ + PAGED_CODE(); + DBG_ENTER("(Property->Value=%d)", pProperty->Value); + + NTSTATUS Status = m_Sensor->SetExposure(pProperty); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Get [legacy] KSPROPERTY_CAMERACONTROL_FOCUS +NTSTATUS +CCaptureFilter:: +GetFocus( + _Inout_ PKSPROPERTY_CAMERACONTROL_S pProperty +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = m_Sensor->GetFocus(pProperty); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Set [legacy] KSPROPERTY_CAMERACONTROL_FOCUS +NTSTATUS +CCaptureFilter:: +SetFocus( + _In_ PKSPROPERTY_CAMERACONTROL_S pProperty +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + m_Sensor->CancelFocus(); + + NTSTATUS Status = m_Sensor->SetFocus(pProperty); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Get [legacy] KSPROPERTY_CAMERACONTROL_ZOOM +NTSTATUS +CCaptureFilter:: +GetZoom( + _Inout_ PKSPROPERTY_CAMERACONTROL_S pProperty +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = m_Sensor->GetZoom(pProperty); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Set [legacy] KSPROPERTY_CAMERACONTROL_ZOOM +NTSTATUS +CCaptureFilter:: +SetZoom( + _In_ PKSPROPERTY_CAMERACONTROL_S pProperty +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = m_Sensor->SetZoom(pProperty); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Get [legacy] KSPROPERTY_CAMERACONTROL_ZOOM_RELATIVE +NTSTATUS +CCaptureFilter:: +GetZoomRelative( + _Inout_ PKSPROPERTY_CAMERACONTROL_S pProperty +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = m_Sensor->GetZoomRelative(pProperty); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Set [legacy] KSPROPERTY_CAMERACONTROL_ZOOM_RELATIVE +NTSTATUS +CCaptureFilter:: +SetZoomRelative( + _In_ PKSPROPERTY_CAMERACONTROL_S pProperty +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = m_Sensor->SetZoomRelative(pProperty); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_PAN +NTSTATUS +CCaptureFilter:: +GetPan( + _Inout_ PKSPROPERTY_CAMERACONTROL_S pProperty +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = m_Sensor->GetPan(pProperty); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Set KSPROPERTY_CAMERACONTROL_PAN +NTSTATUS +CCaptureFilter:: +SetPan( + _In_ PKSPROPERTY_CAMERACONTROL_S pProperty +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = m_Sensor->SetPan(pProperty); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_ROLL +NTSTATUS +CCaptureFilter:: +GetRoll( + _Inout_ PKSPROPERTY_CAMERACONTROL_S pProperty +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = m_Sensor->GetRoll(pProperty); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Set KSPROPERTY_CAMERACONTROL_ROLL +NTSTATUS +CCaptureFilter:: +SetRoll( + _In_ PKSPROPERTY_CAMERACONTROL_S pProperty +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = m_Sensor->SetRoll(pProperty); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_TILT +NTSTATUS +CCaptureFilter:: +GetTilt( + _Inout_ PKSPROPERTY_CAMERACONTROL_S pProperty +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = m_Sensor->GetTilt(pProperty); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Set KSPROPERTY_CAMERACONTROL_TILT +NTSTATUS +CCaptureFilter:: +SetTilt( + _In_ PKSPROPERTY_CAMERACONTROL_S pProperty +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = m_Sensor->SetTilt(pProperty); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Get KSPROPERTY_CAMERACONTROL_FOCAL_LENGTH +NTSTATUS +CCaptureFilter:: +GetFocalLength( + _Inout_ PKSPROPERTY_CAMERACONTROL_FOCAL_LENGTH_S pProperty +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = m_Sensor->GetFocalLength(pProperty); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Set KSPROPERTY_CAMERACONTROL_FOCAL_LENGTH +NTSTATUS +CCaptureFilter:: +SetFocalLength( + _In_ PKSPROPERTY_CAMERACONTROL_FOCAL_LENGTH_S pProperty +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = m_Sensor->SetFocalLength(pProperty); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Get KSPROPERTY_VIDEOPROCAMP_BACKLIGHT_COMPENSATION +NTSTATUS +CCaptureFilter:: +GetBacklightCompensation( + _Inout_ PKSPROPERTY_VIDEOPROCAMP_S pProperty +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = m_Sensor->GetBacklightCompensation(pProperty); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Set KSPROPERTY_VIDEOPROCAMP_BACKLIGHT_COMPENSATION +NTSTATUS +CCaptureFilter:: +SetBacklightCompensation( + _In_ PKSPROPERTY_VIDEOPROCAMP_S pProperty +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = m_Sensor->SetBacklightCompensation(pProperty); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Get KSPROPERTY_VIDEOPROCAMP_BRIGHTNESS +NTSTATUS +CCaptureFilter:: +GetBrightness( + _Inout_ PKSPROPERTY_VIDEOPROCAMP_S pProperty +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = m_Sensor->GetBrightness(pProperty); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Set KSPROPERTY_VIDEOPROCAMP_BRIGHTNESS +NTSTATUS +CCaptureFilter:: +SetBrightness( + _In_ PKSPROPERTY_VIDEOPROCAMP_S pProperty +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = m_Sensor->SetBrightness(pProperty); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Get KSPROPERTY_VIDEOPROCAMP_CONTRAST +NTSTATUS +CCaptureFilter:: +GetContrast( + _Inout_ PKSPROPERTY_VIDEOPROCAMP_S pProperty +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = m_Sensor->GetContrast(pProperty); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Set KSPROPERTY_VIDEOPROCAMP_CONTRAST +NTSTATUS +CCaptureFilter:: +SetContrast( + _In_ PKSPROPERTY_VIDEOPROCAMP_S pProperty +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = m_Sensor->SetContrast(pProperty); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Get KSPROPERTY_VIDEOPROCAMP_HUE +NTSTATUS +CCaptureFilter:: +GetHue( + _Inout_ PKSPROPERTY_VIDEOPROCAMP_S pProperty +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = m_Sensor->GetHue(pProperty); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Set KSPROPERTY_VIDEOPROCAMP_HUE +NTSTATUS +CCaptureFilter:: +SetHue( + _In_ PKSPROPERTY_VIDEOPROCAMP_S pProperty +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = m_Sensor->SetHue(pProperty); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Get [legacy] KSPROPERTY_VIDEOPROCAMP_WHITEBALANCE +NTSTATUS +CCaptureFilter:: +GetWhiteBalance( + _Inout_ PKSPROPERTY_VIDEOPROCAMP_S pProperty +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = m_Sensor->GetWhiteBalance(pProperty); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Set [legacy] KSPROPERTY_VIDEOPROCAMP_WHITEBALANCE +NTSTATUS +CCaptureFilter:: +SetWhiteBalance( + _In_ PKSPROPERTY_VIDEOPROCAMP_S pProperty +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = m_Sensor->SetWhiteBalance(pProperty); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Get KSPROPERTY_VIDEOPROCAMP_POWERLINE_FREQUENCY +NTSTATUS +CCaptureFilter:: +GetPowerlineFreq( + _Inout_ PKSPROPERTY_VIDEOPROCAMP_S pProperty +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = m_Sensor->GetPowerlineFreq(pProperty); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Set KSPROPERTY_VIDEOPROCAMP_POWERLINE_FREQUENCY +NTSTATUS +CCaptureFilter:: +SetPowerlineFreq( + _In_ PKSPROPERTY_VIDEOPROCAMP_S pProperty +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = m_Sensor->SetPowerlineFreq(pProperty); + + DBG_LEAVE("()=0x%08X", Status); + return Status; +} + +// Get KSPROPERTY_VIDEOCONTROL_MODE. +NTSTATUS +CCaptureFilter:: +GetVideoControlMode( + _Inout_ KSPROPERTY_VIDEOCONTROL_MODE_S *pMode +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( m_Sensor->IsStillIndex(pMode->StreamIndex) ) + { + Status = m_Sensor->GetVideoControlMode( pMode ); + } + + DBG_LEAVE("( Pin=%d, Mode=0x%08X )=0x%08X", + pMode->StreamIndex, pMode->Mode, Status ); + return Status; +} + +// Set KSPROPERTY_VIDEOCONTROL_MODE. +NTSTATUS +CCaptureFilter:: +SetVideoControlMode( + _In_ KSPROPERTY_VIDEOCONTROL_MODE_S *pMode +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( m_Sensor->IsStillIndex(pMode->StreamIndex) ) + { + KSPROPERTY_VIDEOCONTROL_CAPS_S Caps; + RtlZeroMemory( &Caps, sizeof(Caps) ); + Caps.StreamIndex = pMode->StreamIndex; + + Status = m_Sensor->GetVideoControlCaps( &Caps ); + if( NT_SUCCESS(Status) && + pMode->Mode == (pMode->Mode & (LONG)Caps.VideoControlCaps ) ) + { + DBG_TRACE("Mode=0x%08X, Caps.Mode=0x%08X", pMode->Mode, Caps.VideoControlCaps); + Status = m_Sensor->SetVideoControlMode( pMode ); + } + else + { + Status = STATUS_INVALID_PARAMETER; + } + } + + DBG_LEAVE("( Pin=%d, Mode=0x%08X )=0x%08X", + pMode->StreamIndex, pMode->Mode, Status ); + return Status; +} + +// Get KSPROPERTY_VIDEOCONTROL_CAPS. +NTSTATUS +CCaptureFilter:: +GetVideoControlCaps( + _Inout_ KSPROPERTY_VIDEOCONTROL_CAPS_S *pCaps +) +{ + PAGED_CODE(); + DBG_ENTER("()"); + + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + if( m_Sensor->IsValidIndex(pCaps->StreamIndex) ) + { + Status = m_Sensor->GetVideoControlCaps( pCaps ); + } + + DBG_LEAVE("( Pin=%d, Caps=0x%08X )=0x%08X", + pCaps->StreamIndex, pCaps->VideoControlCaps, Status ); + return Status; +} + |
