2016-09-19 13:57:57 -07:00
/*
Copyright ( c ) 2015 - 2016 , Intel Corporation
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions are met :
* Redistributions of source code must retain the above copyright notice ,
this list of conditions and the following disclaimer .
* Redistributions in binary form must reproduce the above copyright
notice , this list of conditions and the following disclaimer in the
documentation and / or other materials provided with the distribution .
* Neither the name of Intel Corporation nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission .
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS " AS IS "
AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL
DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY ,
OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*/
// SegProc.h : Declaration of the CSegProc
# pragma once
# include "resource.h" // main symbols
# include "seg_service.h"
# include "pxcsession.h"
# include "pxcsensemanager.h"
# include "pxc3dseg.h"
# include <string>
# include <mutex>
# include <thread>
# include <condition_variable>
# if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
# error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
# endif
using namespace ATL ;
/* Number of milliseconds service waits for worker thread to start */
# define START_TIMEOUT 2000
# define USE_DEFAULT_PROPERTY_VALUE -1
// CSegProc
typedef struct _frameHeader
{
int width ;
int height ;
int pitch ;
long long timestamp ;
int frameNumber ;
} FrameHeader ;
class ATL_NO_VTABLE CSegProc :
public CComObjectRootEx < CComSingleThreadModel > ,
public CComCoClass < CSegProc , & CLSID_SegProc > ,
public IDispatchImpl < ISegProc , & IID_ISegProc , & LIBID_seg_serviceLib , /*wMajor =*/ 1 , /*wMinor =*/ 0 > ,
public PXCSenseManager : : Handler
{
private :
enum {
DEPTH_PROPERTY_NORMAL_MODE = 0x03 ,
DEPTH_PROPERTY_HDR_MODE = 0x200
} ;
// Service state section
HANDLE m_loopThreadHandle ;
bool m_procRun ;
HANDLE m_hStartedEvt ;
// Shared memory section
std : : wstring m_bufferName ;
HANDLE m_sharedBufferHandle ;
LPCTSTR m_sharedBuffer ;
bool m_bufferRealloc ;
// Frames section
int m_currentFrame ;
int m_frameToRead ;
size_t m_frameSize ;
const static size_t headerSize = sizeof ( FrameHeader ) ;
CRITICAL_SECTION m_frameAccess [ 2 ] ;
// RSSDK section
PXCSenseManager * m_senseManager ;
PXC3DSeg * m_segModule ;
int m_fps ;
int m_motionRangeTradeOff ;
bool m_processing ;
bool m_isPause ;
std : : condition_variable m_cvPause ;
std : : mutex m_pauseMtx ;
pxcStatus PXCAPI OnModuleSetProfile ( pxcUID /*mid*/ , PXCBase * /*module*/ ) override
{
PXCCaptureManager * captureMgr = m_senseManager - > QueryCaptureManager ( ) ;
if ( ! captureMgr | | m_fps ! = 60 )
return PXC_STATUS_NO_ERROR ;
PXCCapture : : Device * device = captureMgr - > QueryDevice ( ) ;
PXCCapture : : Device : : PropertyInfo propInfo = device - > QueryIVCAMMotionRangeTradeOffInfo ( ) ;
int value = m_motionRangeTradeOff ;
if ( m_motionRangeTradeOff = = USE_DEFAULT_PROPERTY_VALUE )
value = ( int ) propInfo . defaultValue ;
device - > SetIVCAMMotionRangeTradeOff ( value ) ;
return PXC_STATUS_NO_ERROR ;
}
pxcStatus senseMgrInit ( )
{
pxcStatus status = PXC_STATUS_NO_ERROR ;
status = m_senseManager - > Enable3DSeg ( nullptr ) ;
if ( status ! = PXC_STATUS_NO_ERROR )
return status ;
m_segModule = m_senseManager - > Query3DSeg ( ) ;
if ( ! m_segModule )
return PXC_STATUS_DATA_UNAVAILABLE ;
for ( int i = 0 ; ; i + + ) {
pxcStatus status = PXC_STATUS_NO_ERROR ;
PXCVideoModule : : DataDesc currentProfile = { } ;
status = m_segModule - > QueryInstance < PXCVideoModule > ( ) - > QueryCaptureProfile ( i , & currentProfile ) ;
if ( status ! = PXC_STATUS_NO_ERROR )
return status ;
if ( ( currentProfile . streams . depth . propertySet ! = DEPTH_PROPERTY_NORMAL_MODE )
| | ( currentProfile . streams . depth . options & PXCCapture : : Device : : STREAM_OPTION_DEPTH_CONFIDENCE ) ) {
continue ;
}
m_senseManager - > QueryCaptureManager ( ) - > FilterByStreamProfiles ( nullptr ) ;
m_senseManager - > QueryCaptureManager ( ) - > FilterByStreamProfiles ( nullptr ) ;
2017-12-06 16:07:23 -08:00
m_senseManager - > QueryCaptureManager ( ) - > FilterByStreamProfiles ( PXCCapture : : StreamType : : STREAM_TYPE_COLOR , 0 , 0 , ( pxcF32 ) m_fps ) ;
m_senseManager - > QueryCaptureManager ( ) - > FilterByStreamProfiles ( PXCCapture : : StreamType : : STREAM_TYPE_DEPTH , 0 , 0 , ( pxcF32 ) m_fps ) ;
2016-09-19 13:57:57 -07:00
status = m_senseManager - > EnableStreams ( & currentProfile ) ;
if ( status ! = PXC_STATUS_NO_ERROR )
return status ;
status = m_senseManager - > Init ( this ) ;
if ( status = = PXC_STATUS_NO_ERROR ) {
m_isPause = false ;
break ;
}
else {
continue ;
}
}
return status ;
}
HRESULT reinit ( )
{
m_isPause = true ;
//wait_for_end_processing
while ( m_processing )
std : : this_thread : : yield ( ) ;
std : : unique_lock < std : : mutex > lck ( m_pauseMtx ) ;
m_senseManager - > Close ( ) ;
2017-12-06 16:07:23 -08:00
senseMgrInit ( ) ;
2016-09-19 13:57:57 -07:00
m_isPause = false ;
m_cvPause . notify_one ( ) ;
return S_OK ;
}
/* -----------------------------------------------------------------
* Modification by Jim
*
* To avoid linker issues with the RSSDK . lib files , load via
* LoadLibrary
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
typedef int ( WINAPI * PXCSessionCreateProc ) ( PXCSession * * output ) ;
static HMODULE GetLib ( )
{
HMODULE lib = nullptr ;
HKEY key = nullptr ;
wchar_t path [ 1024 ] ;
LONG res = RegOpenKeyExW ( HKEY_LOCAL_MACHINE , L " Software \\ Intel \\ RSSDK \\ Dispatch " , 0 , KEY_QUERY_VALUE , & key ) ;
if ( res ! = ERROR_SUCCESS ) {
res = RegOpenKeyExW ( HKEY_LOCAL_MACHINE , L " Software \\ Intel \\ RSSDK \\ v10 \\ Dispatch " , 0 , KEY_QUERY_VALUE , & key ) ;
}
if ( res ! = ERROR_SUCCESS )
return nullptr ;
DWORD size = 1024 ;
res = RegQueryValueExW ( key , L " Core " , nullptr , nullptr , ( LPBYTE ) path , & size ) ;
if ( res = = ERROR_SUCCESS ) {
lib = LoadLibrary ( path ) ;
}
RegCloseKey ( key ) ;
return lib ;
}
static PXCSenseManager * CreateSessionInstance ( )
{
static bool initialized = false ;
static HMODULE lib = nullptr ;
static PXCSessionCreateProc create = nullptr ;
if ( ! initialized ) {
lib = GetLib ( ) ;
create = ( PXCSessionCreateProc ) GetProcAddress ( lib , " PXCSession_Create " ) ;
initialized = true ;
}
if ( ! lib | | ! create )
return nullptr ;
PXCSession * session = nullptr ;
int test = create ( & session ) ;
if ( test ! = 0 | | ! session )
return nullptr ;
PXCSenseManager * sm = session - > CreateSenseManager ( ) ;
session - > Release ( ) ;
return sm ;
}
/* -----------------------------------------------------------------
* End Modification
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
public :
CSegProc ( )
: m_isPause ( true )
, m_fps ( 0 )
, m_processing ( false )
, m_motionRangeTradeOff ( USE_DEFAULT_PROPERTY_VALUE )
{
}
DECLARE_REGISTRY_RESOURCEID ( IDR_SEGPROC )
DECLARE_NOT_AGGREGATABLE ( CSegProc )
BEGIN_COM_MAP ( CSegProc )
COM_INTERFACE_ENTRY ( ISegProc )
COM_INTERFACE_ENTRY ( IDispatch )
END_COM_MAP ( )
DECLARE_PROTECT_FINAL_CONSTRUCT ( )
HRESULT FinalConstruct ( )
{
return S_OK ;
}
void FinalRelease ( )
{
}
HRESULT STDMETHODCALLTYPE Init ( LPCWSTR bufferName )
{
m_frameSize = 16 ;
m_frameToRead = - 1 ;
m_bufferName = bufferName ;
m_sharedBufferHandle = CreateFileMapping ( INVALID_HANDLE_VALUE , NULL , PAGE_READWRITE , 0 , 2 * m_frameSize , m_bufferName . c_str ( ) ) ;
if ( m_sharedBufferHandle = = NULL )
return E_FAIL ;
m_sharedBuffer = ( LPTSTR ) MapViewOfFile ( m_sharedBufferHandle , FILE_MAP_ALL_ACCESS , 0 , 0 , 32 ) ;
if ( m_sharedBuffer = = NULL )
{
CloseHandle ( m_sharedBufferHandle ) ;
return E_FAIL ;
}
m_procRun = false ;
/* -----------------------------------------------------------------
* Modification by Jim
*
* To avoid linker issues with the RSSDK . lib files , load via
* LoadLibrary .
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
m_senseManager = CreateSessionInstance ( ) ;
/* -----------------------------------------------------------------
* End Modification
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
if ( ! m_senseManager )
return E_FAIL ;
pxcStatus status = senseMgrInit ( ) ;
if ( status < PXC_STATUS_NO_ERROR )
return E_FAIL ;
m_hStartedEvt = CreateEvent ( NULL , FALSE , FALSE , TEXT ( " StartEvent " ) ) ;
if ( m_hStartedEvt = = NULL )
{
return E_FAIL ;
}
if ( m_procRun )
return E_FAIL ;
m_loopThreadHandle = CreateThread ( NULL , 0 , & CSegProc : : LoopStub , this , 0 , NULL ) ;
if ( m_loopThreadHandle = = NULL )
{
return E_OUTOFMEMORY ;
}
/* Waiting thread for start */
DWORD dwWaitResult = WaitForSingleObject ( m_hStartedEvt , INFINITE ) ;
switch ( dwWaitResult )
{
case WAIT_OBJECT_0 :
return S_OK ;
}
return E_FAIL ;
}
static DWORD WINAPI LoopStub ( LPVOID lpParam )
{
2017-12-06 16:07:23 -08:00
if ( ! lpParam ) return ( DWORD ) - 1 ;
2016-09-19 13:57:57 -07:00
return ( ( CSegProc * ) lpParam ) - > Loop ( NULL ) ;
}
DWORD WINAPI Loop ( LPVOID /*lpParam*/ )
{
static const int headerSize = sizeof ( FrameHeader ) ;
InitializeCriticalSection ( & m_frameAccess [ 0 ] ) ;
InitializeCriticalSection ( & m_frameAccess [ 1 ] ) ;
// Loop through frames
m_procRun = true ;
SetEvent ( m_hStartedEvt ) ;
m_currentFrame = 0 ;
int frameCounter = 0 ;
while ( m_procRun )
{
m_processing = false ;
if ( m_isPause )
{
std : : unique_lock < std : : mutex > lck ( m_pauseMtx ) ;
while ( m_isPause )
m_cvPause . wait ( lck ) ;
}
m_processing = true ;
if ( m_senseManager - > AcquireFrame ( true ) ! = PXC_STATUS_NO_ERROR )
{
continue ;
}
EnterCriticalSection ( & m_frameAccess [ m_currentFrame ] ) ;
{
PXCImage * segImage = m_segModule - > AcquireSegmentedImage ( ) ;
if ( segImage )
{
PXCImage : : ImageData segData ;
ZeroMemory ( & segData , sizeof ( segData ) ) ;
pxcStatus sts = segImage - > AcquireAccess ( PXCImage : : ACCESS_READ , PXCImage : : PixelFormat : : PIXEL_FORMAT_RGB32 , & segData ) ;
if ( sts > = PXC_STATUS_NO_ERROR )
{
int newFrameSize = segData . pitches [ 0 ] * segImage - > QueryInfo ( ) . height + headerSize ;
if ( newFrameSize ! = ( int ) m_frameSize )
{
EnterCriticalSection ( & m_frameAccess [ 1 - m_currentFrame ] ) ;
ResizeBuffer ( newFrameSize * 2 ) ;
m_frameSize = newFrameSize ;
m_bufferRealloc = true ;
LeaveCriticalSection ( & m_frameAccess [ 1 - m_currentFrame ] ) ;
}
int offset = m_frameSize * m_currentFrame ;
//((int*)m_sharedBuffer)[offset+0] = segImage->QueryInfo().width;
//((int*)m_sharedBuffer)[offset+1] = segImage->QueryInfo().height;
//((int*)m_sharedBuffer)[offset+2] = segData.pitches[0];
char * ptr = ( ( char * ) m_sharedBuffer ) + offset ;
PXCImage : : ImageInfo info = segImage - > QueryInfo ( ) ;
FrameHeader * fhPtr = ( FrameHeader * ) ptr ;
fhPtr - > width = info . width ;
fhPtr - > height = info . height ;
fhPtr - > pitch = segData . pitches [ 0 ] ;
fhPtr - > timestamp = segImage - > QueryTimeStamp ( ) ;
fhPtr - > frameNumber = frameCounter ;
memcpy_s ( ( void * ) ( ( char * ) m_sharedBuffer + offset + headerSize ) , m_frameSize - headerSize , segData . planes [ 0 ] , m_frameSize - headerSize ) ;
segImage - > ReleaseAccess ( & segData ) ;
}
segImage - > Release ( ) ;
}
}
m_currentFrame = 1 - m_currentFrame ;
LeaveCriticalSection ( & m_frameAccess [ m_currentFrame ] ) ;
m_senseManager - > ReleaseFrame ( ) ;
frameCounter + + ;
}
DeleteCriticalSection ( & m_frameAccess [ 0 ] ) ;
DeleteCriticalSection ( & m_frameAccess [ 1 ] ) ;
return 0 ;
}
// Bad function for the reason of outside syncronization
HRESULT ResizeBuffer ( size_t newSize )
{
UnmapViewOfFile ( m_sharedBuffer ) ;
CloseHandle ( m_sharedBufferHandle ) ;
m_sharedBufferHandle = CreateFileMapping ( INVALID_HANDLE_VALUE , NULL , PAGE_READWRITE , 0 , newSize , m_bufferName . c_str ( ) ) ;
if ( ! m_sharedBufferHandle )
return E_ACCESSDENIED ;
m_sharedBuffer = ( LPTSTR ) MapViewOfFile ( m_sharedBufferHandle , FILE_MAP_ALL_ACCESS , 0 , 0 , newSize ) ;
if ( ! m_sharedBuffer )
{
CloseHandle ( m_sharedBufferHandle ) ;
return E_OUTOFMEMORY ;
}
ZeroMemory ( ( void * ) m_sharedBuffer , newSize ) ;
return S_OK ;
}
HRESULT STDMETHODCALLTYPE LockBuffer ( int * frameId , int * frameSize , int * bufferRealloc )
{
if ( ! m_procRun | | m_frameToRead ! = - 1 )
return E_FAIL ;
m_frameToRead = 1 - m_currentFrame ;
EnterCriticalSection ( & m_frameAccess [ m_frameToRead ] ) ;
* frameId = m_frameToRead ;
if ( m_bufferRealloc )
{
* bufferRealloc = ( int ) m_bufferRealloc ;
m_bufferRealloc = false ;
}
else
* bufferRealloc = false ;
* frameSize = m_frameSize ;
return S_OK ;
}
HRESULT STDMETHODCALLTYPE UnlockBuffer ( )
{
if ( ! m_procRun | | m_frameToRead = = - 1 )
{
return E_FAIL ;
}
LeaveCriticalSection ( & m_frameAccess [ m_frameToRead ] ) ;
m_frameToRead = - 1 ;
return S_OK ;
}
HRESULT STDMETHODCALLTYPE Stop ( )
{
if ( ! m_procRun )
{
return E_FAIL ;
}
m_procRun = false ;
WaitForSingleObject ( m_loopThreadHandle , INFINITE ) ;
m_senseManager - > Close ( ) ;
return S_OK ;
}
HRESULT STDMETHODCALLTYPE SetFps ( int fps )
{
if ( m_fps = = fps )
return S_OK ;
m_fps = fps ;
if ( m_procRun )
return reinit ( ) ;
return S_OK ;
}
HRESULT STDMETHODCALLTYPE GetFps ( int * fps )
{
* fps = m_fps ;
return S_OK ;
}
HRESULT STDMETHODCALLTYPE SetIVCAMMotionRangeTradeOff ( int value )
{
if ( m_motionRangeTradeOff = = value )
return S_OK ;
m_motionRangeTradeOff = value ;
if ( m_procRun )
return reinit ( ) ;
return S_OK ;
}
HRESULT STDMETHODCALLTYPE GetIVCAMMotionRangeTradeOff ( int * value )
{
* value = m_motionRangeTradeOff ;
return S_OK ;
}
} ;
OBJECT_ENTRY_AUTO ( __uuidof ( SegProc ) , CSegProc )