diff options
| author | Wei Mao <[email protected]> | 2017-03-17 20:14:57 -0700 |
|---|---|---|
| committer | Wei Mao <[email protected]> | 2017-03-17 20:14:57 -0700 |
| commit | 406cf3e4c6cd251bf69cdd8d7b6433f3477d3980 (patch) | |
| tree | 15ca9253d190ab5e16cde06526dc17b486f32a22 /AVStream/avscamera/sys/hwsim.cpp | |
| parent | 1a3e0d580380e58bf336a242d2affc8a1e2d1ddf (diff) | |
Use lower case
Diffstat (limited to 'AVStream/avscamera/sys/hwsim.cpp')
| -rw-r--r-- | AVStream/avscamera/sys/hwsim.cpp | 1409 |
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(); -} |
