summaryrefslogtreecommitdiff
path: root/AVStream/avscamera/sys/hwsim.cpp
diff options
context:
space:
mode:
authorWei Mao <[email protected]>2017-03-17 20:14:57 -0700
committerWei Mao <[email protected]>2017-03-17 20:14:57 -0700
commit406cf3e4c6cd251bf69cdd8d7b6433f3477d3980 (patch)
tree15ca9253d190ab5e16cde06526dc17b486f32a22 /AVStream/avscamera/sys/hwsim.cpp
parent1a3e0d580380e58bf336a242d2affc8a1e2d1ddf (diff)
Use lower case
Diffstat (limited to 'AVStream/avscamera/sys/hwsim.cpp')
-rw-r--r--AVStream/avscamera/sys/hwsim.cpp1409
1 files changed, 0 insertions, 1409 deletions
diff --git a/AVStream/avscamera/sys/hwsim.cpp b/AVStream/avscamera/sys/hwsim.cpp
deleted file mode 100644
index f00a4684..00000000
--- a/AVStream/avscamera/sys/hwsim.cpp
+++ /dev/null
@@ -1,1409 +0,0 @@
-/**************************************************************************
-
- A/V Stream Camera Sample
-
- Copyright (c) 2001, Microsoft Corporation.
-
- File:
-
- hwsim.cpp
-
- Abstract:
-
- This file contains the implementation of CHardwareSimulation used to
- simulate a camera's capture stream.
-
- Our simulation cannot mimic a real camera with any precision. A real
- camera would likely have dedicated hardware to provide interrupts, do
- DMA transfers of frames from an internal buffer as well as do scaling
- and on-the-fly colorspace and planar format conversions so as to supply
- frames for preview, video and photo in varying resolutions and
- colorspaces.
-
- This simulation does not have such hardware, so instead it synthesizes
- a frame on the fly for each local pin as required. The frame is
- synthesized from common state information, so the images produced
- should be comparable from pin to pin. CHardwareSimulation is used as
- a base class for each simulated pin / hardware.
-
- History:
-
- created 3/9/2001
-
-**************************************************************************/
-
-#include "Common.h"
-
-/**************************************************************************
-
- PAGEABLE CODE
-
-**************************************************************************/
-
-#ifdef ALLOC_PRAGMA
-#pragma code_seg("PAGE")
-#endif // ALLOC_PRAGMA
-
-
-inline
-CHwSimTimer::
-CHwSimTimer(
- _In_ CHardwareSimulation *Parent
-)
- : KPassiveTimer( Parent->m_Sensor->GetDeviceObject() )
- , m_Parent( Parent )
-/*++
-
-Routine Description:
-
- CHwSimTimer object construction.
-
-Arguments:
-
- Parent -
- The parent CHardwareSimulation.
-
-Return Value:
-
- None
-
---*/
-{
- PAGED_CODE();
-}
-
-void
-CHwSimTimer::Handler(
- _In_opt_ PVOID Context
-)
-/*++
-
-Routine Description:
-
- Punts to the HardwareSim...
-
-Arguments:
-
- Context -
- Our parent CHardwareSimulation.
-
-Return Value:
-
- None
-
---*/
-{
- PAGED_CODE();
- ((CHardwareSimulation *) Context)->FakeHardware();
-}
-
-/*************************************************/
-
-CHardwareSimulation::
-CHardwareSimulation (
- _Inout_ CSensor *Sensor,
- _In_ LONG PinID
-)
- : m_Sensor (Sensor)
- , m_IsrTimer(this)
- , m_ScatterGatherMappingsMax (SCATTER_GATHER_MAPPINGS_MAX)
- , m_TimePerFrame(ONESECOND/30)
- , m_PinID(PinID)
- , m_Synthesizer(nullptr)
- , m_Width(0)
- , m_Height(0)
- , m_ImageSize(0)
- , m_PinState(PinStopped)
- , m_NumMappingsCompleted(0)
- , m_ScatterGatherMappingsQueued(0)
- , m_ScatterGatherBytesQueued(0)
- , m_NumFramesSkipped(0)
- , m_InterruptTime(0)
- , m_LastReportedExposureTime(DEF_EXPOSURE_TIME) // Assume the default exposure time for now.
- , m_LastReportedWhiteBalance(0)
- , m_FaceDetectionDelay(1) // Start out reporting immediately.
-
-/*++
-
-Routine Description:
-
- CHardwareSimulation Construction.
-
-Arguments:
-
- Sensor -
- The parent CSensor object that contains state for the controls.
- PinID -
- The pin index.
-
-Return Value:
-
- None
-
---*/
-{
-
- PAGED_CODE();
-
- //
- // Initialize the timer's, and locks necessary to simulate this hardware.
- //
- InitializeListHead (&m_ScatterGatherMappings);
-
- //
- // Initialize the entry lookaside.
- //
- ExInitializeNPagedLookasideList (
- &m_ScatterGatherLookaside,
- NULL,
- NULL,
- POOL_NX_ALLOCATION,
- sizeof (SCATTER_GATHER_ENTRY),
- 'nEGS',
- 0
- );
-
- m_StartTime.QuadPart = 0;
-}
-
-CHardwareSimulation::
-~CHardwareSimulation()
-{
- PAGED_CODE();
-
- // Cancel the timer, just in case its running.
- m_IsrTimer.Cancel();
-
- //
- // Delete the scatter / gather lookaside list.
- //
- ExDeleteNPagedLookasideList (&m_ScatterGatherLookaside);
-}
-
-/*************************************************/
-
-BOOLEAN
-CHardwareSimulation::
-Initialize()
-
-/*++
-
-Routine Description:
-
- Initialize the hardware simulation
-
-Arguments:
-
- [none]
-
-Return Value:
-
- TRUE - CHardwareSimulation is fully initialized.
-
---*/
-
-{
- PAGED_CODE();
-
- return m_IsrTimer.IsValid() ;
-}
-
-/*************************************************/
-
-NTSTATUS
-CHardwareSimulation::
-Start (
- IN CSynthesizer *ImageSynth,
- IN LONGLONG TimePerFrame,
- IN ULONG Width,
- IN ULONG Height,
- IN ULONG ImageSize
-)
-
-/*++
-
-Routine Description:
-
- Start the hardware simulation. This will kick the interrupts on,
- begin issuing DPC's, filling in capture information, etc...
- We keep track of starvation starting at this point.
-
-Arguments:
-
- ImageSynth -
- The image synthesizer to use to generate pictures to display
- on the capture buffer.
-
- TimePerFrame -
- The time per frame... we issue interrupts this often.
-
- Width -
- The image width
-
- Height -
- The image height
-
- ImageSize -
- The size of the image. We allocate a temporary scratch buffer
- based on this size to fake hardware.
-
-Return Value:
-
- Success / Failure (typical failure will be out of memory on the
- scratch buffer, etc...)
-
---*/
-
-{
-
- PAGED_CODE();
-
- // Prevent state-changes during this call.
- KScopedMutex Lock(m_ListLock);
-
- NTSTATUS Status = STATUS_SUCCESS;
-
- m_Synthesizer = ImageSynth;
- m_TimePerFrame = TimePerFrame;
- m_ImageSize = ImageSize;
- m_Height = Height;
- m_Width = Width;
-
- m_NumMappingsCompleted = 0;
- m_ScatterGatherMappingsQueued = 0;
- m_NumFramesSkipped = 0;
- m_InterruptTime = 0;
-
- KeQuerySystemTime (&m_StartTime);
-
- if( !m_Synthesizer->Initialize() )
- {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- }
-
- //
- // If everything is ok, start issuing interrupts.
- //
- if (NT_SUCCESS (Status))
- {
- LARGE_INTEGER NextTime;
- NextTime.QuadPart = m_StartTime.QuadPart + m_TimePerFrame;
-
- m_PinState = PinRunning;
- m_IsrTimer.Set( NextTime );
- }
-
- return Status;
-}
-
-/*************************************************/
-
-NTSTATUS
-CHardwareSimulation::
-Pause (
- BOOLEAN Pausing
-)
-
-/*++
-
-Routine Description:
-
- Pause the hardware simulation... When the hardware simulation is told
- to pause, it stops stops the timer, but it does not reset the counters.
-
-Arguments:
-
- Pausing -
- Indicates whether the hardware is pausing or not.
-
- TRUE -
- Pause the hardware
-
- FALSE -
- Unpause the hardware from a previous pause
-
-
-Return Value:
-
- Success / Failure
-
---*/
-
-{
-
- PAGED_CODE();
-
- {
- // Prevent state-changes during this call.
- KScopedMutex Lock(m_ListLock);
-
- if (Pausing && m_PinState == PinRunning)
- {
- //
- // If we were running, stop completing mappings, etc...
- //
- m_PinState = PinPaused;
- }
- else if (!Pausing && m_PinState == PinPaused)
- {
- //
- // For unpausing the hardware, we need to compute the relative time
- // and restart interrupts.
- //
- LARGE_INTEGER UnpauseTime;
-
- KeQuerySystemTime (&UnpauseTime);
- m_InterruptTime = (ULONG) (
- (UnpauseTime.QuadPart - m_StartTime.QuadPart) /
- m_TimePerFrame
- );
-
- UnpauseTime.QuadPart = m_StartTime.QuadPart +
- (m_InterruptTime + 1) * m_TimePerFrame;
-
- m_PinState = PinRunning;
- m_IsrTimer.Set( UnpauseTime );
- }
- }
-
- // If we are pausing, it's best to stop the timer and not wait for another frame.
- if( Pausing )
- {
- m_IsrTimer.Cancel();
- }
-
- return STATUS_SUCCESS;
-}
-
-NTSTATUS
-CHardwareSimulation::
-Stop()
-
-/*++
-
-Routine Description:
-
- Stop the hardware simulation...
-
- For us, stop the timer, free the synthesizer and flush the queue.
-
-Arguments:
-
- None
-
-Return Value:
-
- Success / Failure
-
---*/
-
-{
- PAGED_CODE();
-
- //
- // If the hardware is told to stop while it's running, we need to
- // halt the interrupts first. If we're already paused, this has
- // already been done.
- //
-
- DBG_ENTER("(): m_PinID=%d", m_PinID);
-
- BOOLEAN bCancel = FALSE;
-
- {
- // Prevent state-changes during this call.
- KScopedMutex Lock(m_ListLock);
-
- bCancel = (m_PinState == PinRunning);
- m_PinState = PinStopped;
-
- // Free the synthesis buffer.
- m_Synthesizer->Destroy();
-
- //
- // Free S/G buffer
- //
- FreeSGList( &m_ScatterGatherMappings, L"StreamPointer Stop SG List" );
-
- m_ScatterGatherMappingsQueued=0;
- m_NumMappingsCompleted = 0;
- m_ScatterGatherBytesQueued = 0;
- }
-
- // If running, stop the timer to make sure we don't try to deliver one last frame.
- if( bCancel )
- {
- m_IsrTimer.Cancel();
- }
-
- return STATUS_SUCCESS;
-}
-
-NTSTATUS
-CHardwareSimulation::
-Reset()
-{
- PAGED_CODE();
-
- KScopedMutex Lock( m_ListLock );
- DBG_ENTER("(): m_PinID=%d", m_PinID);
-
- FreeSGList( &m_ScatterGatherMappings, L"StreamPointer Reset SG List" );
-
- m_ScatterGatherMappingsQueued=0;
- m_NumMappingsCompleted = 0;
- m_ScatterGatherBytesQueued = 0;
-
- DBG_LEAVE("(): m_PinID=%d", m_PinID);
- return STATUS_SUCCESS;
-}
-
-NTSTATUS
-CHardwareSimulation::
-Reset (IN PKSPIN Pin)
-{
- PAGED_CODE();
-
- NTSTATUS status = STATUS_SUCCESS;
- if(Pin->ResetState == KSRESET_END)
- {
- KsPinAttemptProcessing(Pin, TRUE);
- }
- else
- {
- status = Reset();
- }
-
- return status;
-}
-
-ULONG
-CHardwareSimulation::
-ReadNumberOfMappingsCompleted()
-
-/*++
-
-Routine Description:
-
- Read the number of scatter / gather mappings which have been
- completed since the last reset of the simulated hardware
-
-Arguments:
-
- None
-
-Return Value:
-
- Total number of completed mappings.
-
---*/
-
-{
- PAGED_CODE();
-
- return m_NumMappingsCompleted;
-}
-
-/*************************************************/
-
-
-ULONG
-CHardwareSimulation::
-ProgramScatterGatherMappings (
- IN PKSSTREAM_POINTER *Clone,
- IN PUCHAR *Buffer,
- IN PKSMAPPING Mappings,
- IN ULONG MappingsCount,
- IN ULONG MappingStride
-)
-
-/*++
-
-Routine Description:
-
- Add a single entry to our queue. In practice our simulation can only
- accept one frame at a time, but we still base this code off of the
- avshws sample.
-
-Arguments:
-
- Buffer -
- The virtual address of the buffer mapped by the mapping list
-
- ClonePointer
- The KSStreamClone Pointer to be associated with the entry item
-
- Mappings -
- The KSMAPPINGS array corresponding to the buffer
-
- MappingsCount -
- The number of mappings in the mappings array
-
- MappingStride -
- The mapping stride used in initialization of AVStream DMA
-
-Return Value:
-
- Number of mappings actually inserted.
-
---*/
-
-{
- PAGED_CODE();
-
- ULONG MappingsInserted = 0;
-
- DBG_ENTER("(Clone=%p, Buffer=%p, MappingsCount=%d)",
- Clone, Buffer, MappingsCount);
-
- //
- // Protect our S/G list with a spinlock.
- //
- KScopedMutex Lock( m_ListLock );
-
- //
- // Loop through the scatter / gather list and break the buffer up into
- // chunks equal to the scatter / gather mappings. Stuff the virtual
- // addresses of these chunks on a list somewhere. We update the buffer
- // pointer the caller passes as a more convenient way of doing this.
- //
- // If I could just remap physical in the list to virtual easily here,
- // I wouldn't need to do it.
- //
- do
- {
- PSCATTER_GATHER_ENTRY Entry =
- reinterpret_cast <PSCATTER_GATHER_ENTRY> (
- ExAllocateFromNPagedLookasideList (
- &m_ScatterGatherLookaside
- )
- );
-
- if (!Entry)
- {
- break;
- }
-
- Entry ->CloneEntry = nullptr;
- Entry -> Virtual = nullptr;
- Entry -> ByteCount = 0;
-
-
- Entry ->CloneEntry = *Clone;
- Entry -> CloneEntry -> StreamHeader -> PresentationTime.Time = 0;
- Entry -> CloneEntry -> StreamHeader -> OptionsFlags &= ~KSSTREAM_HEADER_OPTIONSF_TIMEVALID;
-
- Entry -> Virtual = *Buffer;
- Entry -> ByteCount = MappingsCount;
- Entry->PhotoConfirmationInfo = PHOTOCONFIRMATION_INFO();
-
- //
- // Move forward a specific number of bytes in chunking this into
- // mapping sized va buffers.
- //
- *Buffer += MappingsCount;
- Mappings = reinterpret_cast <PKSMAPPING> (
- (reinterpret_cast <PUCHAR> (Mappings) + MappingStride)
- );
-
- InsertTailList (&m_ScatterGatherMappings, &(Entry -> ListEntry));
- m_ScatterGatherMappingsQueued++;
- MappingsInserted = MappingsCount;
- DBG_TRACE("m_ScatterGatherMappingsQueued=%d", m_ScatterGatherMappingsQueued);
- m_ScatterGatherBytesQueued += MappingsCount;
-
- }
- while(FALSE);
-
- DBG_LEAVE(" MappingsInserted=%d", MappingsInserted );
-
- return MappingsInserted;
-
-}
-
-/**************************************************************************
-
- The following are helper functions used in the production of metadata.
- Since this is just a simulation, most "auto" modes get converted into
- a random value that is in range.
-
- While simple, this still requires writing a helper function for each
- piece of data.
-
-**************************************************************************/
-
-//
-// Translate Exposure settings into a "current value".
-//
-LONGLONG
-CHardwareSimulation::
-GetCurrentExposureTime()
-{
- PAGED_CODE();
-
- ISP_FRAME_SETTINGS *pSettings = GetIspSettings();
- LONGLONG Value = 0;
- LPCSTR Mode = "[UNKNOWN]";
-
- if( pSettings->ExposureMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO )
- {
- // Get random value in global setting's bound (LONG)
- // I'm abandoning the reported min/max and using something more reasonable.
- Value = GetRandom( MIN_EXPOSURE_TIME*5, DEF_EXPOSURE_TIME*5 );
- Mode = "KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO";
- }
-
- if( pSettings->ExposureMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL )
- {
- Value = pSettings->ExposureSetting.VideoProc.Value.ll;
- Mode = "KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL";
- }
-
- // Locked just reports the last value set...
- if( pSettings->ExposureMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK )
- {
- Value = m_LastReportedExposureTime;
- Mode = "KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK";
- }
-
- DBG_TRACE("ExposureMode=0x%016llX (%s), Time=%llu00ns, LastReported=%llu00ns",
- pSettings->ExposureMode, Mode, Value, m_LastReportedExposureTime );
-
- m_LastReportedExposureTime = Value;
- return Value;
-}
-
-//
-// Translate White Balance into a "current value".
-//
-ULONG
-CHardwareSimulation::
-GetCurrentWhiteBalance()
-{
- PAGED_CODE();
-
- ISP_FRAME_SETTINGS *pSettings = GetIspSettings();
- ULONG Value = 0;
-
- if( pSettings->WhiteBalanceMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO )
- {
- Value = (ULONG) GetRandom( pSettings->WhiteBalanceSetting.Min, pSettings->WhiteBalanceSetting.Max );
- }
-
- if( pSettings->WhiteBalanceMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL )
- {
- Value = pSettings->WhiteBalanceSetting.VideoProc.Value.ul;
- }
-
- // Locked just reports the last value set...
- if( pSettings->WhiteBalanceMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK )
- {
- Value = m_LastReportedWhiteBalance;
- }
-
- m_LastReportedWhiteBalance= Value;
- return Value;
-}
-
-//
-// Translate ISO settings into a "current value".
-//
-ULONG
-CHardwareSimulation::
-GetCurrentISOSpeed()
-{
- PAGED_CODE();
-
- ISP_FRAME_SETTINGS *pSettings = GetIspSettings();
- ULONG Value = 0;
-
- if( pSettings->ISOMode & KSCAMERA_EXTENDEDPROP_ISO_AUTO )
- {
- Value = GetRandom( (ULONG) 50, (ULONG) 3200 );
- }
- else if( pSettings->ISOMode & KSCAMERA_EXTENDEDPROP_ISO_MANUAL )
- {
- Value = pSettings->ISOValue;
- }
- else
- {
- Value = // Try converting any legacy presets to a manual value.
- IsoPreset2Value( pSettings->ISOMode );
- }
- return Value;
-}
-
-//
-// Translate Exposure Mode to an Exif Exposure Program value
-//
-USHORT
-CHardwareSimulation::
-GetExposureProgram()
-{
- PAGED_CODE();
-
- ISP_FRAME_SETTINGS *pSettings = GetIspSettings();
- USHORT Value = 0; // Undefined.
-
- if( pSettings->ExposureMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL )
- {
- Value = 1; // Manual
- }
- if( pSettings->ExposureMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO )
- {
- Value = 2; // Normal
- }
-
- // TODO: Extend SceneMode to ISP settings so I can use it here to capture Portrait mode, etc.
- return Value;
-}
-
-/*************************************************/
-
-//
-// Emit metadata here that is common to all pins.
-//
-// All derived classes' EmitMetadata() function must
-// call this function first.
-//
-void
-CHardwareSimulation::
-EmitMetadata(
- _Inout_ PKSSTREAM_HEADER pStreamHeader
-)
-{
- PAGED_CODE();
-
- NT_ASSERT(pStreamHeader);
-
- if (0 != (pStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_METADATA))
- {
- PKS_FRAME_INFO pFrameInfo = (PKS_FRAME_INFO)(pStreamHeader + 1);
- PKSSTREAM_METADATA_INFO pMetadata = (PKSSTREAM_METADATA_INFO) (pFrameInfo + 1);
- //PBYTE pData = (PBYTE) pMetadata->SystemVa;
- //ULONG BytesLeft = pMetadata->BufferSize;
-
- // A real driver might write focus state or other info here. We've got nothing.
- pMetadata->UsedSize = 0;
- }
- else
- {
- DBG_TRACE("Metadata not present...");
- }
-}
-
-void
-CHardwareSimulation::
-EmitFaceMetadata(
- _Inout_ PKSSTREAM_HEADER pStreamHeader,
- _In_ ULONG Count,
- _In_ ULONGLONG Flags,
- _In_ ULONG DelayLimit
-)
-/*++
-
-Routine Description:
-
- Helper function that emits FaceDetection metadata.
-
- Note: This function assumes a metadata buffer is present.
-
-Arguments:
-
- pStreamHeader -
- The frame's stream header.
-
- Count -
- The maximum number of faces to detect.
-
- Flags -
- A combination of the KSCAMERA_EXTENDEDPROP_FACEDETECTION_BLINK and
- KSCAMERA_EXTENDEDPROP_FACEDETECTION_BLINK flags passed to the face
- detection control. Used to decide what characterization data to
- present in the metadata.
-
- DelayLimit -
- The maximum number of frames to delay before generating the next
- face detection.
-
-Return Value:
-
- None.
-
---*/
-{
- PAGED_CODE();
-
- NT_ASSERT(pStreamHeader);
- NT_ASSERT(Count <= SIZEOF_ARRAY(m_LastFaceDetect.Data));
-
- // Do nothing if we're turned on, but they want no faces.
- if( Count==0 )
- {
- return;
- }
-
- if( --m_FaceDetectionDelay != 0 || // Count down our random delay for new face data.
- Count > m_LastFaceDetect.Count ) // Make sure we never emit more faces than requested.
- {
- ULONG CountReported = GetRandom( 0, Count );
-
- DBG_TRACE("Generating new faces (Count=%d, Flags=0x%016llX, Delay=%d)...",
- Count, Flags, DelayLimit);
-
- // Synthesize a new set of "detected" faces...
- m_LastFaceDetect.Header.MetadataId = (ULONG) MetadataId_Custom_FaceDetection;
- m_LastFaceDetect.Header.Size =
- sizeof(CAMERA_METADATA_FACEHEADER) + (sizeof(METADATA_FACEDATA) * CountReported);
-
- m_LastFaceDetect.Count = CountReported;
- m_LastFaceDetect.Flags = Flags;
- m_LastFaceDetect.Timestamp = pStreamHeader->PresentationTime.Time ;
-
- DBG_TRACE("Count=%d, Flags=0x%016llX, Time=0x%016llX",
- m_LastFaceDetect.Count,
- m_LastFaceDetect.Flags,
- m_LastFaceDetect.Timestamp );
-
- // Report face data...
- for( ULONG i=0; i<CountReported; i++ )
- {
- RtlZeroMemory( &m_LastFaceDetect.Data[i], sizeof(m_LastFaceDetect.Data[i]) );
-
- RECT &rect = m_LastFaceDetect.Data[i].Region;
- rect.top = GetRandom((LONG)0, TO_Q31(1)-2);
- rect.left = GetRandom((LONG)0, TO_Q31(1)-2);
- rect.bottom = GetRandom(rect.top+1, TO_Q31(1)-1);
- rect.right = GetRandom(rect.left+1, TO_Q31(1)-1);
-
- m_LastFaceDetect.Data[i].confidenceLevel = GetRandom((ULONG)25, 100); // Don't bother reporting really low confidence faces.
-
- DBG_TRACE(" #%d: [(0x%08X,0x%08X), (0x%08X,0x%08X)](Conf=%d%%)",
- i,
- rect.top, rect.left, rect.bottom, rect.right,
- m_LastFaceDetect.Data[i].confidenceLevel);
-
- if( Flags & KSCAMERA_EXTENDEDPROP_FACEDETECTION_BLINK )
- {
- m_LastFaceDetect.Data[i].BlinkScoreLeft = GetRandom((ULONG)0, 100); // Should really skew these numbers more in favor of no blink.
- m_LastFaceDetect.Data[i].BlinkScoreRight = GetRandom((ULONG)0, 100);
-
- DBG_TRACE(" --- Blink(left=%d%%, right=%d%%)",
- m_LastFaceDetect.Data[i].BlinkScoreLeft,
- m_LastFaceDetect.Data[i].BlinkScoreRight);
- }
-
- if( Flags & KSCAMERA_EXTENDEDPROP_FACEDETECTION_SMILE )
- {
- m_LastFaceDetect.Data[i].FacialExpression = GetRandom((ULONG)0, 1) ? EXPRESSION_SMILE : 0;
- m_LastFaceDetect.Data[i].FacialExpressionScore = GetRandom((ULONG)0, 100);
-
- DBG_TRACE(" --- Smile(exp=%s, score=%d%%)",
- (m_LastFaceDetect.Data[i].FacialExpression==EXPRESSION_SMILE ? "Smile":"[unknown]"),
- m_LastFaceDetect.Data[i].FacialExpressionScore);
- }
- }
-
- // Randomly choose when to generate new facedetection data.
- m_FaceDetectionDelay = GetRandom( 1, DelayLimit );
- DBG_TRACE("Delay to next is %d", m_FaceDetectionDelay);
- }
-
- // The flags can change between face detection updates.
- // Drop the additional characterization data immediately, if requested.
- // We can hardly add it that fast since it might not be generated straight away.
- ULONGLONG LostFlags = m_LastFaceDetect.Flags & ~Flags;
- for( ULONG i=0; i<m_LastFaceDetect.Count; i++ )
- {
- if( LostFlags & KSCAMERA_EXTENDEDPROP_FACEDETECTION_BLINK )
- {
- m_LastFaceDetect.Data[i].BlinkScoreLeft = 0;
- m_LastFaceDetect.Data[i].BlinkScoreRight = 0;
- }
- if( LostFlags & KSCAMERA_EXTENDEDPROP_FACEDETECTION_SMILE )
- {
- m_LastFaceDetect.Data[i].FacialExpression = 0;
- m_LastFaceDetect.Data[i].FacialExpressionScore = 0;
- }
- }
- m_LastFaceDetect.Flags &= Flags;
-
- PKS_FRAME_INFO pFrameInfo = (PKS_FRAME_INFO)(pStreamHeader + 1);
- PKSSTREAM_METADATA_INFO pMetadata = (PKSSTREAM_METADATA_INFO) (pFrameInfo + 1);
- ULONG BytesLeft = pMetadata->BufferSize - pMetadata->UsedSize;
-
- // Write Face Detection Info here
- // Note: If we derived Video and Preview from a common base class, we
- // might use that to emit this information for both types.
- if( BytesLeft >= m_LastFaceDetect.Header.Size )
- {
- // Always write the most recently generated face detection info.
- RtlCopyMemory(
- ((PBYTE)pMetadata->SystemVa) + pMetadata->UsedSize,
- &m_LastFaceDetect,
- m_LastFaceDetect.Header.Size );
-
- DBG_TRACE("Emitting Face metadata...");
-
- BytesLeft -= m_LastFaceDetect.Header.Size;
- pMetadata->UsedSize += m_LastFaceDetect.Header.Size;
- }
- else
- {
- DBG_TRACE("WARNING: Out of metadata buffer...");
- }
-}
-
-//
-// PIN_STATE text for debug output.
-//
-static
-const char *
-GetPinStateTxt( PIN_STATE state )
-{
- PAGED_CODE();
-
- switch( state )
- {
- case PinStopped:
- return "STOPPED";
- case PinPaused:
- return "PAUSED";
- case PinRunning:
- return "RUNNING";
- }
- return "[UNKNOWN]";
-}
-
-NTSTATUS
-CHardwareSimulation::
-FillScatterGatherBuffers()
-
-/*++
-
-Routine Description:
-
- The hardware has synthesized a buffer and we're to fill a frame buffer.
-
-Arguments:
-
- None
-
-Return Value:
-
- Success / Failure
-
---*/
-
-{
- PAGED_CODE();
-
- DBG_ENTER("() m_PinState=%s, m_PinID=0x%08X, m_ImageSize=0x%08X, m_ScatterGatherMappingsQueued=%u, "
- "m_ScatterGatherBytesQueue=0x%08X",
- GetPinStateTxt(m_PinState),
- m_PinID, m_ImageSize, m_ScatterGatherMappingsQueued, m_ScatterGatherBytesQueued);
-
- NTSTATUS ntStatus = STATUS_SUCCESS;
-
- ULONG BufferRemaining = m_ImageSize;
-
- //
- // If there isn't a frame buffer queued, we justskip the frame and consider
- // it starvation.
- //
- while (BufferRemaining &&
- !IsListEmpty(&m_ScatterGatherMappings) &&
- m_ScatterGatherBytesQueued >= BufferRemaining)
- {
- LIST_ENTRY *listEntry = RemoveHeadList (&m_ScatterGatherMappings);
- m_ScatterGatherMappingsQueued--;
-
- PSCATTER_GATHER_ENTRY SGEntry =
- reinterpret_cast <PSCATTER_GATHER_ENTRY> (
- CONTAINING_RECORD (
- listEntry,
- SCATTER_GATHER_ENTRY,
- ListEntry
- )
- );
-
- // Deal with cancellation.
- PIRP pIrp = KsStreamPointerGetIrp(SGEntry->CloneEntry, FALSE, FALSE);
- if (pIrp)
- {
- if (pIrp->Cancel)
- {
- DBG_TRACE( "Cancelling..." );
- FreeSGEntry( listEntry, L"StreamPointer Cancel SG List" );
- continue;
- }
- }
-
- //
- // Since we're software, we'll be accessing this by virtual address...
- //
- ULONG Stride = 0;
- if ( SGEntry->CloneEntry -> StreamHeader -> Size >= sizeof (KSSTREAM_HEADER) +
- sizeof (KS_FRAME_INFO))
- {
- PKS_FRAME_INFO FrameInfo = reinterpret_cast <PKS_FRAME_INFO> (SGEntry->CloneEntry->StreamHeader+1);
- Stride = (ULONG) ABS(FrameInfo->lSurfacePitch);
- }
-
- // Have the synthesizer output a frame to the buffer.
- ULONG BytesCopied = m_Synthesizer->DoCommit( SGEntry->Virtual, SGEntry->ByteCount, Stride );
- NT_ASSERT( BytesCopied );
- DBG_TRACE( "BytesCopied = %d", BytesCopied );
-
- //Adding time stamp
- if(m_PhotoConfirmationEntry.isRequired())
- {
- SGEntry -> CloneEntry -> StreamHeader -> PresentationTime.Time =
- m_PhotoConfirmationEntry.getTime();
- DBG_TRACE("Using Photo Confirmation time = 0x%016llX", m_PhotoConfirmationEntry.getTime());
- }
- else
- {
- SGEntry -> CloneEntry -> StreamHeader -> PresentationTime.Time = ConvertQPCtoTimeStamp(NULL);
- DBG_TRACE("PresentationTime = 0x%016llX", SGEntry->CloneEntry->StreamHeader->PresentationTime.Time );
- }
-
- SGEntry -> CloneEntry -> StreamHeader -> PresentationTime.Numerator =
- SGEntry -> CloneEntry -> StreamHeader -> PresentationTime.Denominator = 1;
-
- SGEntry -> CloneEntry -> StreamHeader -> OptionsFlags |= KSSTREAM_HEADER_OPTIONSF_TIMEVALID ;
-
- // Add metadata to the sample.
- EmitMetadata( SGEntry -> CloneEntry -> StreamHeader );
-
- BufferRemaining = 0; //-= BytesCopied;
- m_NumMappingsCompleted++;
- m_ScatterGatherBytesQueued -= SGEntry -> ByteCount;
-
- //
- // Release the scatter / gather entry back to our lookaside.
- //
- ExFreeToNPagedLookasideList (
- &m_ScatterGatherLookaside,
- reinterpret_cast <PVOID> (SGEntry)
- );
-
- }
-
- // Report an error if we used the last buffer.
- if (BufferRemaining)
- {
- //DBG_TRACE("BufferRemaining=%u", BufferRemaining);
- ntStatus = STATUS_INSUFFICIENT_RESOURCES;
- }
-
- DBG_LEAVE("() = 0x%08X", ntStatus);
- return ntStatus;
-}
-
-/**************************************************************************
-
- Debug helpers
-
-**************************************************************************/
-
-PCCHAR
-DVS_Text( ULONGLONG Flags )
-{
- PAGED_CODE();
-
- switch( Flags )
- {
- case KSCAMERA_EXTENDEDPROP_VIDEOSTABILIZATION_OFF: return "Off";
- case KSCAMERA_EXTENDEDPROP_VIDEOSTABILIZATION_ON: return "On";
- case KSCAMERA_EXTENDEDPROP_VIDEOSTABILIZATION_AUTO: return "Auto";
- default:
- {
- static
- CHAR buffer[32];
-
- RtlStringCbPrintfA(buffer, sizeof(buffer), "Unknown [0x%016llX]", Flags);
- return (PCCHAR) buffer;
- }
- }
-}
-
-PCCHAR
-OIS_Text( ULONGLONG Flags )
-{
- PAGED_CODE();
-
- switch( Flags )
- {
- case KSCAMERA_EXTENDEDPROP_OIS_OFF: return "Off";
- case KSCAMERA_EXTENDEDPROP_OIS_ON: return "On";
- case KSCAMERA_EXTENDEDPROP_OIS_AUTO: return "Auto";
- default:
- {
- static
- CHAR buffer[32];
-
- RtlStringCbPrintfA(buffer, sizeof(buffer), "Unknown [0x%016llX]", Flags);
- return (PCCHAR) buffer;
- }
- }
-}
-
-/**************************************************************************/
-
-void
-CHardwareSimulation::
-FakeHardware (
-)
-
-/*++
-
-Routine Description:
-
- Simulate an interrupt and what the hardware would have done in the
- time since the previous interrupt.
-
-Arguments:
-
- None
-
-Return Value:
-
- None
-
---*/
-
-{
- PAGED_CODE();
-
- KScopedMutex Lock( m_ListLock );
-
- m_InterruptTime++;
-
- //
- // The hardware can be in a pause state in which case, it issues interrupts
- // but does not complete mappings. In this case, don't bother synthesizing
- // a frame and doing the work of looking through the mappings table.
- //
- if (m_PinState == PinRunning)
- {
- //
- // Generate a "time stamp" just to overlay it onto the capture image.
- // It makes it more exciting than bars that do nothing.
- //
- ULONGLONG time = ConvertQPCtoTimeStamp(NULL);
- DBG_TRACE("QPC=0x%016llX", time);
-
- m_Synthesizer->SetFrameNumber( m_InterruptTime );
- m_Synthesizer->SetRelativePts( (m_InterruptTime + 1) * m_TimePerFrame );
- m_Synthesizer->SetQpcTime( time );
-
- m_Synthesizer->DoSynthesize();
-
- CHAR Text[64];
-
- CExtendedProperty Control;
- m_Sensor->GetVideoStabilization( &Control );
- RtlStringCbPrintfA(Text, sizeof(Text), "DVS: %s", DVS_Text(Control.Flags));
- m_Synthesizer->OverlayText( 0, m_Height-38, 1, Text, TRANSPARENT, TEXT_COLOR );
-
- m_Sensor->GetOpticalImageStabilization( &Control );
- RtlStringCbPrintfA(Text, sizeof(Text), "OIS: %s", OIS_Text(Control.Flags));
- m_Synthesizer->OverlayText( 0, m_Height-48, 1, Text, TRANSPARENT, TEXT_COLOR );
-
- //
- // Fill scatter gather buffers
- //
- if (!NT_SUCCESS (FillScatterGatherBuffers ()))
- {
- InterlockedIncrement (PLONG (&m_NumFramesSkipped));
- }
-
- }
-
- //
- // Issue an interrupt to our hardware sink. This is a "fake" interrupt.
- // It will occur at DISPATCH_LEVEL.
- //
- m_Sensor -> Interrupt (m_PinID);
-
- //
- // Schedule the timer for the next interrupt time, if the pin is still running.
- //
- if( m_PinState == PinRunning )
- {
- LARGE_INTEGER NextTime;
- NextTime.QuadPart = m_StartTime.QuadPart +
- (m_TimePerFrame * (m_InterruptTime + 1));
-
-#ifdef ENABLE_TRACING // To keep us from a tight spin when trying to debug this code...
- LARGE_INTEGER Now;
- KeQuerySystemTime(&Now);
-
- if( Now.QuadPart >= NextTime.QuadPart )
- {
- NextTime.QuadPart = 0LL - m_TimePerFrame ;
- }
-
-#endif
- m_IsrTimer.Set( NextTime );
- }
-}
-
-ULONGLONG
-CHardwareSimulation::
-ConvertQPCtoTimeStamp(
- _In_opt_ PLARGE_INTEGER pQpcTime
-)
-/*++
-
-Routine Description:
-
- Get the QPC measured in 100ns units.
-
-Arguments:
-
- pQpcTime -
- An optional time value to convert. If NULL, use the current QPC.
-
-Return Value:
-
- ULONLONG -
- The time in 100ns increments.
-
---*/
-{
- PAGED_CODE();
-
- LARGE_INTEGER qpcTime = {0};
- LARGE_INTEGER qpcFrequency;
-
- qpcTime = KeQueryPerformanceCounter(&qpcFrequency);
-
- if( pQpcTime )
- {
- qpcTime = *pQpcTime;
- }
-
- return KSCONVERT_PERFORMANCE_TIME( qpcFrequency.QuadPart, qpcTime );
-}
-
-NTSTATUS
-CHardwareSimulation::
-GeneratePhotoConfirmation(
- _In_ ULONG PfsFrameNumber,
- _In_ LONGLONG time
-)
-/*++
-
-Routine Description:
-
- So a photo sim can ask a preview sim for a confirmation frame.
-
-Arguments:
-
- PfsFrameNumber -
- The VPS shot number.
- time -
- The precise time of the associated photo.
-
-Return Value:
-
- None
-
---*/
-{
- PAGED_CODE();
-
- KScopedMutex Lock( m_ListLock );
-
- if( PinRunning != m_PinState )
- {
- return STATUS_DEVICE_NOT_READY;
- }
-
- DBG_ENTER("( Index=%d, Time=0x%016llX )", PfsFrameNumber, time );
-
- m_PhotoConfirmationEntry = PHOTOCONFIRMATION_INFO( PfsFrameNumber, time );
-
- // We basically used the previously synthesized preview image
- NTSTATUS status = FillScatterGatherBuffers();
-
- //Clean up the photo confiramtion flag
- m_PhotoConfirmationEntry = PHOTOCONFIRMATION_INFO();
-
- if(NT_SUCCESS(status))
- {
- m_Sensor->Interrupt (m_PinID);
- }
-
- DBG_LEAVE("() = 0x%08X", status);
-
- return status;
-}
-
-void
-CHardwareSimulation::
-FreeSGEntry(
- _In_ PLIST_ENTRY Entry,
- _In_ PCWSTR EventName,
- _In_opt_ LPCGUID Activity,
- _In_ ULONG DataUsed
-)
-{
- PAGED_CODE();
-
- PSCATTER_GATHER_ENTRY SGEntry =
- reinterpret_cast <PSCATTER_GATHER_ENTRY> (
- CONTAINING_RECORD (
- Entry,
- SCATTER_GATHER_ENTRY,
- ListEntry
- )
- );
-
- NT_ASSERT(SGEntry->CloneEntry);
- NT_ASSERT(SGEntry->CloneEntry->StreamHeader);
-
- SGEntry->CloneEntry->StreamHeader->DataUsed = DataUsed;
-
- KsStreamPointerDelete(SGEntry->CloneEntry);
-
- //
- // Release the scatter / gather entry back to our lookaside.
- //
- ExFreeToNPagedLookasideList (
- &m_ScatterGatherLookaside,
- SGEntry
- );
-}
-
-void
-CHardwareSimulation::
-FreeSGList(
- _In_ PLIST_ENTRY List,
- _In_ PCWSTR EventName,
- _In_opt_ LPCGUID Activity
-)
-{
- PAGED_CODE();
-
- while(!IsListEmpty(List))
- {
- PLIST_ENTRY head = RemoveHeadList(List);
- m_ScatterGatherMappingsQueued--;
- FreeSGEntry( head, EventName, Activity );
- }
-}
-
-//
-// Get the current frame settings.
-//
-ISP_FRAME_SETTINGS *
-CHardwareSimulation::
-GetIspSettings(void)
-{
- PAGED_CODE();
-
- return m_Sensor->GetGlobalIspSettings();
-}