📄 pindevice.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
#define PININTERFACE
#include <windows.h>
#include <pm.h>
#include <Msgqueue.h>
#include <pwinbase.h>
#include "Cs.h"
#include "Csmedia.h"
#include "CameraPDDProps.h"
#include "dstruct.h"
#include "dbgsettings.h"
#include <camera.h>
#include "CameraDriver.h"
#include "PinDriver.h"
#include "wchar.h"
CPinDevice :: CPinDevice( )
{
m_dwMemoryModel = CSPROPERTY_BUFFER_CLIENT_LIMITED;
m_fClientInitialized = false;
m_fDiscontinuity = true;
m_ulPinId = -1; // Invalid Pin Id
m_ulMaxNumOfBuffers = 0;
m_ulFrameSize = 0;
m_ulFramesDropped = 0;
m_ulPictureNumber = 0;
m_RtAveTimePerFrame = 0;
m_hMsgQ = NULL;
m_CsState = CSSTATE_STOP;
m_msStart = 0xFFFFFFFF;
m_msLastPT = 0;
m_pStreamDescriptorList = NULL;
m_dwBufferCount = 0;
m_lStillCount = 0;
InitializeCriticalSection( &m_csStreamBuffer );
InitializeCriticalSection( &m_csStreamIO );
}
CPinDevice :: ~CPinDevice( )
{
ResetBufferList( );
if ( NULL != m_hMsgQ )
{
CloseMsgQueue( m_hMsgQ );
}
if ( NULL != m_pStreamDescriptorList )
{
LocalFree( m_pStreamDescriptorList );
m_pStreamDescriptorList = NULL;
}
m_CsState = CSSTATE_STOP;
DeleteCriticalSection( &m_csStreamBuffer );
DeleteCriticalSection( &m_csStreamIO );
}
bool CPinDevice :: InitializeSubDevice( PCAMERADEVICE pCamDevice )
{
TCHAR *tszLibraryName = NULL;
TCHAR *tszFunctionName = NULL;
DWORD dwDataSize = 0;
DWORD dwDataType = 0;
m_pCamAdapter = pCamDevice ;
if (NULL == m_pCamAdapter)
{
return false ;
}
return true ;
}
DWORD CPinDevice :: CloseSubDevice()
{
DWORD dwRet = FALSE;
dwRet = m_pCamAdapter->DecrCInstances( m_ulPinId ) ;
if( dwRet )
{
dwRet = m_pCamAdapter->PDDClosePin( m_ulPinId );
}
return dwRet;
}
DWORD CPinDevice :: StreamInstantiate( PCSPROPERTY_STREAMEX_S pCsPropStreamEx, PUCHAR pOutBuf, DWORD OutBufLen, PDWORD pdwBytesTransferred )
{
DWORD dwError = ERROR_INVALID_PARAMETER;
HANDLE hProcess = NULL;
PCS_DATARANGE_VIDEO pCsDataRangeVid = NULL;
if ( -1 != m_ulPinId )
{
DEBUGMSG(ZONE_IOCTL|ZONE_ERROR, (_T("PIN_IOControl(%08x): Pin %d is already instantiated.\r\n"), this, m_ulPinId )) ;
return dwError ;
}
if( NULL == m_pCamAdapter )
{
DEBUGMSG(ZONE_IOCTL|ZONE_ERROR, (_T("PIN_IOControl(%08x): Initialization incomplete.\r\n"), this, m_ulPinId )) ;
return dwError;
}
if ( false == m_pCamAdapter->IsValidPin( pCsPropStreamEx->CsPin.PinId ) )
{
DEBUGMSG(ZONE_IOCTL|ZONE_ERROR, (_T("PIN_IOControl(%08x): Invalid Pin Id\r\n"), this)) ;
return dwError ;
}
m_ulPinId = pCsPropStreamEx->CsPin.PinId ;
SENSORMODEINFO SensorModeInfo;
if( ERROR_SUCCESS != m_pCamAdapter->PDDGetPinInfo( m_ulPinId, &SensorModeInfo ) )
{
DEBUGMSG(ZONE_IOCTL|ZONE_ERROR, (_T("PIN_IOControl(%08x): Failed to retrieve sub-device information\r\n"), this)) ;
return dwError ;
}
m_dwMemoryModel = SensorModeInfo.MemoryModel;
m_ulMaxNumOfBuffers = SensorModeInfo.MaxNumOfBuffers;
// Let us set a default format for this pin
if ( false == m_pCamAdapter->GetPinFormat( m_ulPinId, 1, &pCsDataRangeVid ) )
{
DEBUGMSG(ZONE_IOCTL|ZONE_ERROR, (_T("PIN_IOControl(%08x): No Pin Format provided for pin\r\n"), this)) ;
return dwError ;
}
memcpy(&m_CsDataRangeVideo,pCsDataRangeVid, sizeof(CS_DATARANGE_VIDEO) ) ;
if ( NULL == pCsPropStreamEx->hMsgQueue )
{
DEBUGMSG(ZONE_IOCTL|ZONE_ERROR, (_T("PIN_IOControl(%08x): NULL Handle provided for msgqueue\r\n"), this)) ;
return dwError ;
}
//TODO : Check whether the client created msgqueue with enough buffersize and number of buffers.
MSGQUEUEOPTIONS msgQueueOptions;
msgQueueOptions.bReadAccess = FALSE; // we need write-access to msgqueue
msgQueueOptions.dwSize = sizeof(MSGQUEUEOPTIONS);
hProcess = OpenProcess(NULL, FALSE, GetCallerVMProcessId());
if(NULL == hProcess)
{
DEBUGMSG(ZONE_IOCTL|ZONE_ERROR, (_T("PIN_IOControl(%08x): Failed to open Process\r\n"), this)) ;
return dwError ;
}
ASSERT( m_hMsgQ == NULL );
if ( NULL == (m_hMsgQ = OpenMsgQueue(hProcess, pCsPropStreamEx->hMsgQueue, &msgQueueOptions ) ) )
{
DEBUGMSG(ZONE_IOCTL|ZONE_ERROR, (_T("PIN_IOControl(%08x): Failed to open MsgQueue\r\n"), this)) ;
CloseHandle(hProcess);
return dwError ;
}
CloseHandle(hProcess);
if ( false == m_pCamAdapter->IncrCInstances( m_ulPinId, this ) )
{
DEBUGMSG(ZONE_IOCTL|ZONE_ERROR, (_T("PIN_IOControl(%08x): Pin %d is already instantiated.\r\n"), this, m_ulPinId)) ;
return dwError ;
}
return ERROR_SUCCESS ;
}
void CPinDevice :: SetState( CSSTATE CsState, CSSTATE *CsPrevState )
{
EnterCriticalSection(&m_csStreamIO);
if ( NULL != CsPrevState )
{
*CsPrevState = m_CsState ;
}
//Check if we are not already in the target state
if(m_CsState != CsState)
{
m_CsState = CsState ;
if ( STILL != m_ulPinId || CSSTATE_RUN != CsState )
{
m_pCamAdapter->PDDSetPinState( m_ulPinId, CsState );
}
if( STILL == m_ulPinId && CSSTATE_RUN == CsState )
{
m_fDiscontinuity = true;
}
DEBUGMSG(ZONE_IOCTL|ZONE_ERROR, (_T("Pin: %d Setting State to 0x%X\r\n"), m_ulPinId, CsState)) ;
}
LeaveCriticalSection(&m_csStreamIO);
return ;
}
BOOL CPinDevice::InitMsgQueueDescriptor (PCS_MSGQUEUE_BUFFER pCsMsgQBuff, PCS_STREAM_DESCRIPTOR pCsStreamDesc, PVOID pMappedData, PVOID pUnmappedData, BOOL bBufferFill)
{
PCSSTREAM_HEADER pCsStreamHeader = reinterpret_cast<PCSSTREAM_HEADER>(pCsStreamDesc);
PCS_FRAME_INFO pCsFrameInfo = reinterpret_cast<PCS_FRAME_INFO>(pCsStreamHeader + 1);
// RETAILMSG(1,(TEXT("InitMsgQueueDescriptor\n")));
if(( pCsStreamHeader == NULL ) || ( pCsFrameInfo == NULL ))
{
DEBUGMSG(ZONE_FUNCTION|ZONE_ERROR, (_T("InitMsgQueueDescriptor(%08x): Invalid Stream Descriptor\r\n"), this));
return false;
}
if( bBufferFill )
{
// The buffer fill function must use the pointer that's been mapped into this process.
//RETAILMSG(1,(TEXT("bBufferFill\n")));
pCsStreamHeader->Data = pMappedData;
EnterCriticalSection(&m_csStreamBuffer) ;
pCsStreamHeader->DataUsed = m_pCamAdapter->PDDFillPinBuffer( m_ulPinId, (PUCHAR) pMappedData ) ;
LeaveCriticalSection(&m_csStreamBuffer) ;
pCsFrameInfo->PictureNumber = (LONGLONG)++m_ulPictureNumber;
pCsFrameInfo->DropCount = (LONGLONG)m_ulFramesDropped;
}
// The message queue requires the original pointer value.
pCsStreamHeader->Data = pUnmappedData;
// Init the flags to zero
pCsStreamHeader->OptionsFlags = 0;
// Set the discontinuity flag if frames have been previously
// dropped, and then reset our internal flag
if ( true == m_fDiscontinuity )
{
pCsStreamHeader->OptionsFlags |= CSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY;
m_fDiscontinuity = false;
}
DWORD msNow = GetTickCount();
if (m_msStart == 0xFFFFFFFF)
{
m_msStart = msNow;
}
//
// Return the timestamp for the frame
//
pCsStreamHeader->PresentationTime.Numerator = 1;
pCsStreamHeader->PresentationTime.Denominator = 1;
pCsStreamHeader->Duration = m_RtAveTimePerFrame;
DWORD prevPT = m_msLastPT;
m_msLastPT = msNow - m_msStart;
pCsStreamHeader->PresentationTime.Time = (LONGLONG) m_msLastPT * 10000; // presentation time stamp in 100s of ns
DEBUGMSG(ZONE_FUNCTION, (_T("InitMsgQueueDescriptor: LastPT = %d, elapsed = %d\n"), m_msLastPT, m_msLastPT - prevPT));
// clear the timestamp valid flags
pCsStreamHeader->OptionsFlags &= ~( CSSTREAM_HEADER_OPTIONSF_TIMEVALID | CSSTREAM_HEADER_OPTIONSF_DURATIONVALID );
// Every frame we generate is a key frame (aka SplicePoint)
// Delta frames (B or P) should not set this flag
pCsStreamHeader->OptionsFlags |= CSSTREAM_HEADER_OPTIONSF_SPLICEPOINT;
pCsMsgQBuff->CsMsgQueueHeader.Size = sizeof(CS_MSGQUEUE_HEADER);
pCsMsgQBuff->CsMsgQueueHeader.Flags = FLAG_MSGQ_FRAME_BUFFER;
pCsMsgQBuff->CsMsgQueueHeader.Context = NULL;
//Get the unmarshalled StreamDescriptor in order to send the message to the application
pCsMsgQBuff->pStreamDescriptor = NULL;
for (UINT ii = 0; ii < m_dwBufferCount; ii++)
{
if(m_pStreamDescriptorList[ii].csStreamDescriptorShadow.CsStreamHeader.Data == pUnmappedData)
{
pCsMsgQBuff->pStreamDescriptor = m_pStreamDescriptorList[ii].m_pUnMarshalledStreamDesc;
break;
}
}
if(NULL == pCsMsgQBuff->pStreamDescriptor)
{
DEBUGMSG(ZONE_FUNCTION, (_T("InitMsgQueueDescriptor(%08x): Unable to find Unmarshalled Stream Desc\n"), this));
return FALSE;
}
DEBUGMSG(ZONE_FUNCTION, (_T("InitMsgQueueDescriptor(%08x): Frame buf queued: %d (dropped %d), start %d, time %d\n"),
this,
(LONG)pCsFrameInfo->PictureNumber,
(LONG)pCsFrameInfo->DropCount,
(LONG)m_msStart,
(LONG)(pCsStreamHeader->PresentationTime.Time / 10000)));
return TRUE;
}
void CPinDevice::FlushBufferQueue()
{
PCS_STREAM_DESCRIPTOR pCsStreamDesc = NULL;
PVOID pMappedData = NULL;
PVOID pUnmappedData = NULL;
CS_MSGQUEUE_BUFFER CsMsgQBuff ;
while (( true == RemoveBufferFromList( &pCsStreamDesc, &pMappedData, &pUnmappedData )) && ( NULL != pCsStreamDesc ) && ( m_hMsgQ != NULL ))
{
if (!InitMsgQueueDescriptor (&CsMsgQBuff, pCsStreamDesc, pMappedData, pUnmappedData, FALSE))
{
continue;
}
if ( false == WriteMsgQueue( m_hMsgQ, reinterpret_cast<LPVOID>(&CsMsgQBuff), sizeof(CS_MSGQUEUE_BUFFER), PIN_TIMEOUT, 0 ) )
{
DEBUGMSG(ZONE_FUNCTION|ZONE_ERROR, (_T("PIN_Function(%08x): WriteMsgQueue returned false\r\n"), this));
}
}
return;
}
DWORD CPinDevice :: HandlePinIO()
{
DWORD dwRet = ERROR_SUCCESS;
BOOL bOK = TRUE;
EnterCriticalSection(&m_csStreamIO);
if ( CSSTATE_RUN != m_CsState )
{
LeaveCriticalSection(&m_csStreamIO);
return ERROR_INVALID_STATE;
}
//RETAILMSG(1,(TEXT("HandlePinIO\n")));
PCS_STREAM_DESCRIPTOR pCsStreamDesc = NULL;
PVOID pMappedData = NULL;
PVOID pUnmappedData = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -