win-ivcam: Add Intel RealSense plugin
This commit is contained in:
508
plugins/win-ivcam/seg_service/SegProc.h
Normal file
508
plugins/win-ivcam/seg_service/SegProc.h
Normal file
@@ -0,0 +1,508 @@
|
||||
/*
|
||||
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, ¤tProfile);
|
||||
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);
|
||||
|
||||
m_senseManager->QueryCaptureManager()->FilterByStreamProfiles(PXCCapture::StreamType::STREAM_TYPE_COLOR, 0, 0, m_fps);
|
||||
m_senseManager->QueryCaptureManager()->FilterByStreamProfiles(PXCCapture::StreamType::STREAM_TYPE_DEPTH, 0, 0, m_fps);
|
||||
|
||||
status = m_senseManager->EnableStreams(¤tProfile);
|
||||
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();
|
||||
|
||||
pxcStatus status = senseMgrInit();
|
||||
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)
|
||||
{
|
||||
if (!lpParam) return -1;
|
||||
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)
|
Reference in New Issue
Block a user