| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508 |
- /*
- 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, (pxcF32)m_fps);
- m_senseManager->QueryCaptureManager()->FilterByStreamProfiles(PXCCapture::StreamType::STREAM_TYPE_DEPTH, 0, 0, (pxcF32)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();
- 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 (DWORD)-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)
|