SegProc.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. /*
  2. Copyright (c) 2015-2016, Intel Corporation
  3. Redistribution and use in source and binary forms, with or without
  4. modification, are permitted provided that the following conditions are met:
  5. * Redistributions of source code must retain the above copyright notice,
  6. this list of conditions and the following disclaimer.
  7. * Redistributions in binary form must reproduce the above copyright
  8. notice, this list of conditions and the following disclaimer in the
  9. documentation and/or other materials provided with the distribution.
  10. * Neither the name of Intel Corporation nor the names of its contributors
  11. may be used to endorse or promote products derived from this software
  12. without specific prior written permission.
  13. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  14. AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15. IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  16. DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
  17. FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  18. DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  19. SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  20. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  21. OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  22. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. */
  24. // SegProc.h : Declaration of the CSegProc
  25. #pragma once
  26. #include "resource.h" // main symbols
  27. #include "seg_service.h"
  28. #include "pxcsession.h"
  29. #include "pxcsensemanager.h"
  30. #include "pxc3dseg.h"
  31. #include <string>
  32. #include <mutex>
  33. #include <thread>
  34. #include <condition_variable>
  35. #if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
  36. #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."
  37. #endif
  38. using namespace ATL;
  39. /* Number of milliseconds service waits for worker thread to start */
  40. #define START_TIMEOUT 2000
  41. #define USE_DEFAULT_PROPERTY_VALUE -1
  42. // CSegProc
  43. typedef struct _frameHeader
  44. {
  45. int width;
  46. int height;
  47. int pitch;
  48. long long timestamp;
  49. int frameNumber;
  50. } FrameHeader;
  51. class ATL_NO_VTABLE CSegProc :
  52. public CComObjectRootEx<CComSingleThreadModel>,
  53. public CComCoClass<CSegProc, &CLSID_SegProc>,
  54. public IDispatchImpl<ISegProc, &IID_ISegProc, &LIBID_seg_serviceLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
  55. public PXCSenseManager::Handler
  56. {
  57. private:
  58. enum {
  59. DEPTH_PROPERTY_NORMAL_MODE = 0x03,
  60. DEPTH_PROPERTY_HDR_MODE = 0x200
  61. };
  62. // Service state section
  63. HANDLE m_loopThreadHandle;
  64. bool m_procRun;
  65. HANDLE m_hStartedEvt;
  66. // Shared memory section
  67. std::wstring m_bufferName;
  68. HANDLE m_sharedBufferHandle;
  69. LPCTSTR m_sharedBuffer;
  70. bool m_bufferRealloc;
  71. // Frames section
  72. int m_currentFrame;
  73. int m_frameToRead;
  74. size_t m_frameSize;
  75. const static size_t headerSize = sizeof(FrameHeader);
  76. CRITICAL_SECTION m_frameAccess[2];
  77. // RSSDK section
  78. PXCSenseManager* m_senseManager;
  79. PXC3DSeg* m_segModule;
  80. int m_fps;
  81. int m_motionRangeTradeOff;
  82. bool m_processing;
  83. bool m_isPause;
  84. std::condition_variable m_cvPause;
  85. std::mutex m_pauseMtx;
  86. pxcStatus PXCAPI OnModuleSetProfile(pxcUID /*mid*/, PXCBase* /*module*/) override
  87. {
  88. PXCCaptureManager* captureMgr = m_senseManager->QueryCaptureManager();
  89. if (!captureMgr || m_fps != 60)
  90. return PXC_STATUS_NO_ERROR;
  91. PXCCapture::Device* device = captureMgr->QueryDevice();
  92. PXCCapture::Device::PropertyInfo propInfo = device->QueryIVCAMMotionRangeTradeOffInfo();
  93. int value = m_motionRangeTradeOff;
  94. if (m_motionRangeTradeOff == USE_DEFAULT_PROPERTY_VALUE)
  95. value = (int)propInfo.defaultValue;
  96. device->SetIVCAMMotionRangeTradeOff(value);
  97. return PXC_STATUS_NO_ERROR;
  98. }
  99. pxcStatus senseMgrInit()
  100. {
  101. pxcStatus status = PXC_STATUS_NO_ERROR;
  102. status = m_senseManager->Enable3DSeg(nullptr);
  103. if (status != PXC_STATUS_NO_ERROR)
  104. return status;
  105. m_segModule = m_senseManager->Query3DSeg();
  106. if (!m_segModule)
  107. return PXC_STATUS_DATA_UNAVAILABLE;
  108. for (int i = 0; ; i++) {
  109. pxcStatus status = PXC_STATUS_NO_ERROR;
  110. PXCVideoModule::DataDesc currentProfile = {};
  111. status = m_segModule->QueryInstance<PXCVideoModule>()->QueryCaptureProfile(i, &currentProfile);
  112. if (status != PXC_STATUS_NO_ERROR)
  113. return status;
  114. if ((currentProfile.streams.depth.propertySet != DEPTH_PROPERTY_NORMAL_MODE)
  115. || (currentProfile.streams.depth.options & PXCCapture::Device::STREAM_OPTION_DEPTH_CONFIDENCE)) {
  116. continue;
  117. }
  118. m_senseManager->QueryCaptureManager()->FilterByStreamProfiles(nullptr);
  119. m_senseManager->QueryCaptureManager()->FilterByStreamProfiles(nullptr);
  120. m_senseManager->QueryCaptureManager()->FilterByStreamProfiles(PXCCapture::StreamType::STREAM_TYPE_COLOR, 0, 0, (pxcF32)m_fps);
  121. m_senseManager->QueryCaptureManager()->FilterByStreamProfiles(PXCCapture::StreamType::STREAM_TYPE_DEPTH, 0, 0, (pxcF32)m_fps);
  122. status = m_senseManager->EnableStreams(&currentProfile);
  123. if (status != PXC_STATUS_NO_ERROR)
  124. return status;
  125. status = m_senseManager->Init(this);
  126. if (status == PXC_STATUS_NO_ERROR) {
  127. m_isPause = false;
  128. break;
  129. }
  130. else {
  131. continue;
  132. }
  133. }
  134. return status;
  135. }
  136. HRESULT reinit()
  137. {
  138. m_isPause = true;
  139. //wait_for_end_processing
  140. while (m_processing)
  141. std::this_thread::yield();
  142. std::unique_lock<std::mutex> lck(m_pauseMtx);
  143. m_senseManager->Close();
  144. senseMgrInit();
  145. m_isPause = false;
  146. m_cvPause.notify_one();
  147. return S_OK;
  148. }
  149. /* -----------------------------------------------------------------
  150. * Modification by Jim
  151. *
  152. * To avoid linker issues with the RSSDK .lib files, load via
  153. * LoadLibrary
  154. * ----------------------------------------------------------------- */
  155. typedef int (WINAPI *PXCSessionCreateProc)(PXCSession **output);
  156. static HMODULE GetLib()
  157. {
  158. HMODULE lib = nullptr;
  159. HKEY key = nullptr;
  160. wchar_t path[1024];
  161. LONG res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Intel\\RSSDK\\Dispatch", 0, KEY_QUERY_VALUE, &key);
  162. if (res != ERROR_SUCCESS) {
  163. res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Intel\\RSSDK\\v10\\Dispatch", 0, KEY_QUERY_VALUE, &key);
  164. }
  165. if (res != ERROR_SUCCESS)
  166. return nullptr;
  167. DWORD size = 1024;
  168. res = RegQueryValueExW(key, L"Core", nullptr, nullptr, (LPBYTE)path, &size);
  169. if (res == ERROR_SUCCESS) {
  170. lib = LoadLibrary(path);
  171. }
  172. RegCloseKey(key);
  173. return lib;
  174. }
  175. static PXCSenseManager* CreateSessionInstance()
  176. {
  177. static bool initialized = false;
  178. static HMODULE lib = nullptr;
  179. static PXCSessionCreateProc create = nullptr;
  180. if (!initialized) {
  181. lib = GetLib();
  182. create = (PXCSessionCreateProc)GetProcAddress(lib, "PXCSession_Create");
  183. initialized = true;
  184. }
  185. if (!lib || !create)
  186. return nullptr;
  187. PXCSession *session = nullptr;
  188. int test = create(&session);
  189. if (test != 0 || !session)
  190. return nullptr;
  191. PXCSenseManager *sm = session->CreateSenseManager();
  192. session->Release();
  193. return sm;
  194. }
  195. /* -----------------------------------------------------------------
  196. * End Modification
  197. * ----------------------------------------------------------------- */
  198. public:
  199. CSegProc()
  200. : m_isPause(true)
  201. , m_fps(0)
  202. , m_processing(false)
  203. , m_motionRangeTradeOff(USE_DEFAULT_PROPERTY_VALUE)
  204. {
  205. }
  206. DECLARE_REGISTRY_RESOURCEID(IDR_SEGPROC)
  207. DECLARE_NOT_AGGREGATABLE(CSegProc)
  208. BEGIN_COM_MAP(CSegProc)
  209. COM_INTERFACE_ENTRY(ISegProc)
  210. COM_INTERFACE_ENTRY(IDispatch)
  211. END_COM_MAP()
  212. DECLARE_PROTECT_FINAL_CONSTRUCT()
  213. HRESULT FinalConstruct()
  214. {
  215. return S_OK;
  216. }
  217. void FinalRelease()
  218. {
  219. }
  220. HRESULT STDMETHODCALLTYPE Init(LPCWSTR bufferName)
  221. {
  222. m_frameSize = 16;
  223. m_frameToRead = -1;
  224. m_bufferName = bufferName;
  225. m_sharedBufferHandle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 2 * m_frameSize, m_bufferName.c_str());
  226. if (m_sharedBufferHandle == NULL)
  227. return E_FAIL;
  228. m_sharedBuffer = (LPTSTR)MapViewOfFile(m_sharedBufferHandle, FILE_MAP_ALL_ACCESS, 0, 0, 32);
  229. if (m_sharedBuffer == NULL)
  230. {
  231. CloseHandle(m_sharedBufferHandle);
  232. return E_FAIL;
  233. }
  234. m_procRun = false;
  235. /* -----------------------------------------------------------------
  236. * Modification by Jim
  237. *
  238. * To avoid linker issues with the RSSDK .lib files, load via
  239. * LoadLibrary.
  240. * ----------------------------------------------------------------- */
  241. m_senseManager = CreateSessionInstance();
  242. /* -----------------------------------------------------------------
  243. * End Modification
  244. * ----------------------------------------------------------------- */
  245. if (!m_senseManager)
  246. return E_FAIL;
  247. pxcStatus status = senseMgrInit();
  248. if (status < PXC_STATUS_NO_ERROR)
  249. return E_FAIL;
  250. m_hStartedEvt = CreateEvent(NULL, FALSE, FALSE, TEXT("StartEvent"));
  251. if (m_hStartedEvt == NULL)
  252. {
  253. return E_FAIL;
  254. }
  255. if (m_procRun)
  256. return E_FAIL;
  257. m_loopThreadHandle = CreateThread(NULL, 0, &CSegProc::LoopStub, this, 0, NULL);
  258. if (m_loopThreadHandle == NULL)
  259. {
  260. return E_OUTOFMEMORY;
  261. }
  262. /* Waiting thread for start */
  263. DWORD dwWaitResult = WaitForSingleObject(m_hStartedEvt, INFINITE);
  264. switch (dwWaitResult)
  265. {
  266. case WAIT_OBJECT_0:
  267. return S_OK;
  268. }
  269. return E_FAIL;
  270. }
  271. static DWORD WINAPI LoopStub(LPVOID lpParam)
  272. {
  273. if (!lpParam) return (DWORD)-1;
  274. return ((CSegProc*)lpParam)->Loop(NULL);
  275. }
  276. DWORD WINAPI Loop(LPVOID /*lpParam*/)
  277. {
  278. static const int headerSize = sizeof(FrameHeader);
  279. InitializeCriticalSection(&m_frameAccess[0]);
  280. InitializeCriticalSection(&m_frameAccess[1]);
  281. // Loop through frames
  282. m_procRun = true;
  283. SetEvent(m_hStartedEvt);
  284. m_currentFrame = 0;
  285. int frameCounter = 0;
  286. while (m_procRun)
  287. {
  288. m_processing = false;
  289. if (m_isPause)
  290. {
  291. std::unique_lock<std::mutex> lck(m_pauseMtx);
  292. while (m_isPause)
  293. m_cvPause.wait(lck);
  294. }
  295. m_processing = true;
  296. if (m_senseManager->AcquireFrame(true) != PXC_STATUS_NO_ERROR)
  297. {
  298. continue;
  299. }
  300. EnterCriticalSection(&m_frameAccess[m_currentFrame]);
  301. {
  302. PXCImage* segImage = m_segModule->AcquireSegmentedImage();
  303. if (segImage)
  304. {
  305. PXCImage::ImageData segData;
  306. ZeroMemory(&segData, sizeof(segData));
  307. pxcStatus sts = segImage->AcquireAccess(PXCImage::ACCESS_READ, PXCImage::PixelFormat::PIXEL_FORMAT_RGB32, &segData);
  308. if (sts >= PXC_STATUS_NO_ERROR)
  309. {
  310. int newFrameSize = segData.pitches[0] * segImage->QueryInfo().height + headerSize;
  311. if (newFrameSize != (int)m_frameSize)
  312. {
  313. EnterCriticalSection(&m_frameAccess[1 - m_currentFrame]);
  314. ResizeBuffer(newFrameSize * 2);
  315. m_frameSize = newFrameSize;
  316. m_bufferRealloc = true;
  317. LeaveCriticalSection(&m_frameAccess[1 - m_currentFrame]);
  318. }
  319. int offset = m_frameSize*m_currentFrame;
  320. //((int*)m_sharedBuffer)[offset+0] = segImage->QueryInfo().width;
  321. //((int*)m_sharedBuffer)[offset+1] = segImage->QueryInfo().height;
  322. //((int*)m_sharedBuffer)[offset+2] = segData.pitches[0];
  323. char *ptr = ((char*)m_sharedBuffer) + offset;
  324. PXCImage::ImageInfo info = segImage->QueryInfo();
  325. FrameHeader *fhPtr = (FrameHeader*)ptr;
  326. fhPtr->width = info.width;
  327. fhPtr->height = info.height;
  328. fhPtr->pitch = segData.pitches[0];
  329. fhPtr->timestamp = segImage->QueryTimeStamp();
  330. fhPtr->frameNumber = frameCounter;
  331. memcpy_s((void*)((char*)m_sharedBuffer + offset + headerSize), m_frameSize - headerSize, segData.planes[0], m_frameSize - headerSize);
  332. segImage->ReleaseAccess(&segData);
  333. }
  334. segImage->Release();
  335. }
  336. }
  337. m_currentFrame = 1 - m_currentFrame;
  338. LeaveCriticalSection(&m_frameAccess[m_currentFrame]);
  339. m_senseManager->ReleaseFrame();
  340. frameCounter++;
  341. }
  342. DeleteCriticalSection(&m_frameAccess[0]);
  343. DeleteCriticalSection(&m_frameAccess[1]);
  344. return 0;
  345. }
  346. // Bad function for the reason of outside syncronization
  347. HRESULT ResizeBuffer(size_t newSize)
  348. {
  349. UnmapViewOfFile(m_sharedBuffer);
  350. CloseHandle(m_sharedBufferHandle);
  351. m_sharedBufferHandle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, newSize, m_bufferName.c_str());
  352. if (!m_sharedBufferHandle)
  353. return E_ACCESSDENIED;
  354. m_sharedBuffer = (LPTSTR)MapViewOfFile(m_sharedBufferHandle, FILE_MAP_ALL_ACCESS, 0, 0, newSize);
  355. if (!m_sharedBuffer)
  356. {
  357. CloseHandle(m_sharedBufferHandle);
  358. return E_OUTOFMEMORY;
  359. }
  360. ZeroMemory((void*)m_sharedBuffer, newSize);
  361. return S_OK;
  362. }
  363. HRESULT STDMETHODCALLTYPE LockBuffer(int* frameId, int* frameSize, int* bufferRealloc)
  364. {
  365. if (!m_procRun || m_frameToRead != -1)
  366. return E_FAIL;
  367. m_frameToRead = 1 - m_currentFrame;
  368. EnterCriticalSection(&m_frameAccess[m_frameToRead]);
  369. *frameId = m_frameToRead;
  370. if (m_bufferRealloc)
  371. {
  372. *bufferRealloc = (int)m_bufferRealloc;
  373. m_bufferRealloc = false;
  374. }
  375. else
  376. *bufferRealloc = false;
  377. *frameSize = m_frameSize;
  378. return S_OK;
  379. }
  380. HRESULT STDMETHODCALLTYPE UnlockBuffer()
  381. {
  382. if (!m_procRun || m_frameToRead == -1)
  383. {
  384. return E_FAIL;
  385. }
  386. LeaveCriticalSection(&m_frameAccess[m_frameToRead]);
  387. m_frameToRead = -1;
  388. return S_OK;
  389. }
  390. HRESULT STDMETHODCALLTYPE Stop()
  391. {
  392. if (!m_procRun)
  393. {
  394. return E_FAIL;
  395. }
  396. m_procRun = false;
  397. WaitForSingleObject(m_loopThreadHandle, INFINITE);
  398. m_senseManager->Close();
  399. return S_OK;
  400. }
  401. HRESULT STDMETHODCALLTYPE SetFps(int fps)
  402. {
  403. if (m_fps == fps)
  404. return S_OK;
  405. m_fps = fps;
  406. if (m_procRun)
  407. return reinit();
  408. return S_OK;
  409. }
  410. HRESULT STDMETHODCALLTYPE GetFps(int* fps)
  411. {
  412. *fps = m_fps;
  413. return S_OK;
  414. }
  415. HRESULT STDMETHODCALLTYPE SetIVCAMMotionRangeTradeOff(int value)
  416. {
  417. if (m_motionRangeTradeOff == value)
  418. return S_OK;
  419. m_motionRangeTradeOff = value;
  420. if (m_procRun)
  421. return reinit();
  422. return S_OK;
  423. }
  424. HRESULT STDMETHODCALLTYPE GetIVCAMMotionRangeTradeOff(int* value)
  425. {
  426. *value = m_motionRangeTradeOff;
  427. return S_OK;
  428. }
  429. };
  430. OBJECT_ENTRY_AUTO(__uuidof(SegProc), CSegProc)