@@ -30,6 +30,7 @@ class KinectWrapper
3030
3131 WAITABLE_HANDLE h_statusChangedEvent;
3232 WAITABLE_HANDLE h_bodyFrameEvent;
33+ WAITABLE_HANDLE h_colorFrameEvent;
3334 bool newBodyFrameArrived = false ;
3435
3536 std::array<JointOrientation, JointType_Count> bone_orientations_;
@@ -39,6 +40,7 @@ class KinectWrapper
3940
4041 inline static bool initialized_ = false ;
4142 bool skeleton_tracked_ = false ;
43+ bool rgb_stream_enabled_ = false ;
4244
4345 void updater ()
4446 {
@@ -83,6 +85,20 @@ class KinectWrapper
8385 }
8486 }
8587
88+ void updateColorData ()
89+ {
90+ if (!colorFrameReader)return ; // Give up already
91+
92+ IColorFrame* colorFrame = nullptr ;
93+ colorFrameReader->AcquireLatestFrame (&colorFrame);
94+
95+ if (!colorFrame) return ;
96+ ResetBuffer (CameraBufferSize ()); // Allocate buffer for image for copy
97+
98+ colorFrame->CopyConvertedFrameDataToArray (
99+ CameraBufferSize (), color_buffer_, ColorImageFormat_Bgra);
100+ }
101+
86102 bool initKinect ()
87103 {
88104 // Get a working Kinect Sensor
@@ -130,6 +146,22 @@ class KinectWrapper
130146 if (bodyFrameSource) bodyFrameSource->Release ();
131147 }
132148
149+ void initializeColor ()
150+ {
151+ if (colorFrameReader)
152+ colorFrameReader->Release ();
153+
154+ IColorFrameSource* colorFrameSource;
155+ kinectSensor->get_ColorFrameSource (&colorFrameSource);
156+ colorFrameSource->OpenReader (&colorFrameReader);
157+
158+ // Newfangled event based frame capture
159+ // https://github.com/StevenHickson/PCL_Kinect2SDK/blob/master/src/Microsoft_grabber2.cpp
160+ h_colorFrameEvent = (WAITABLE_HANDLE)CreateEvent (nullptr , FALSE , FALSE , nullptr );
161+ colorFrameReader->SubscribeFrameArrived (&h_colorFrameEvent);
162+ if (colorFrameSource) colorFrameSource->Release ();
163+ }
164+
133165 void terminateSkeleton ()
134166 {
135167 if (!bodyFrameReader)return ; // No need to do anything
@@ -150,6 +182,26 @@ class KinectWrapper
150182 bodyFrameReader = nullptr ;
151183 }
152184
185+ void terminateColor ()
186+ {
187+ if (!colorFrameReader)return ; // No need to do anything
188+ if (FAILED (colorFrameReader->UnsubscribeFrameArrived (h_colorFrameEvent)))
189+ {
190+ throw std::exception (" Couldn't unsubscribe frame!" );
191+ }
192+ __try
193+ {
194+ CloseHandle ((HANDLE)h_colorFrameEvent);
195+ colorFrameReader->Release ();
196+ }
197+ __except (EXCEPTION_EXECUTE_HANDLER)
198+ {
199+ // ignored
200+ }
201+ h_colorFrameEvent = NULL ;
202+ colorFrameReader = nullptr ;
203+ }
204+
153205 HRESULT kinect_status_result ()
154206 {
155207 BOOLEAN avail;
@@ -246,6 +298,7 @@ class KinectWrapper
246298 if (!initialized_) return 1 ;
247299
248300 initializeSkeleton ();
301+ initializeColor ();
249302
250303 // Recreate the updater thread
251304 if (!updater_thread_)
@@ -306,6 +359,24 @@ class KinectWrapper
306359 pArgs->Release (); // Release the frame
307360 }
308361 }
362+
363+ if (h_colorFrameEvent && rgb_stream_enabled_)
364+ if (HANDLE handles[] = {reinterpret_cast <HANDLE>(h_colorFrameEvent)};
365+ // Wait for a frame to arrive, give up after >3s of nothing
366+ MsgWaitForMultipleObjects (_countof (handles), handles,
367+ false , 3000 , QS_ALLINPUT) == WAIT_OBJECT_0)
368+ {
369+ IColorFrameArrivedEventArgs* pArgs = nullptr ;
370+ if (colorFrameReader &&
371+ SUCCEEDED (colorFrameReader->GetFrameArrivedEventData (h_colorFrameEvent, &pArgs)))
372+ {
373+ [&,this ](IColorFrameReader& sender, IColorFrameArrivedEventArgs& eventArgs)
374+ {
375+ updateColorData ();
376+ }(*colorFrameReader, *pArgs);
377+ pArgs->Release (); // Release the frame
378+ }
379+ }
309380 }
310381 }
311382 }
@@ -319,6 +390,7 @@ class KinectWrapper
319390 {
320391 // Protect from null call
321392 terminateSkeleton ();
393+ terminateColor ();
322394
323395 return [&, this ]
324396 {
@@ -376,13 +448,74 @@ class KinectWrapper
376448 return skeleton_positions_;
377449 }
378450
451+ std::tuple<BYTE*, int > color_buffer ()
452+ {
453+ return std::make_tuple (color_buffer_, size_in_bytes_last_);
454+ }
455+
379456 bool skeleton_tracked ()
380457 {
381458 return skeleton_tracked_;
382459 }
383460
461+ void camera_enabled (bool enabled)
462+ {
463+ rgb_stream_enabled_ = enabled;
464+ }
465+
466+ bool camera_enabled (void )
467+ {
468+ return rgb_stream_enabled_;
469+ }
470+
384471 int KinectJointType (int kinectJointType)
385472 {
386473 return KinectJointTypeDictionary.at (static_cast <JointType>(kinectJointType));
387474 }
475+
476+ std::pair<int , int > CameraImageSize ()
477+ {
478+ return std::make_pair (1920 , 1080 );
479+ }
480+
481+ unsigned long CameraBufferSize ()
482+ {
483+ const auto & [width, height] = CameraImageSize ();
484+ return width * height * 4 ;
485+ }
486+
487+ std::pair<int , int > MapCoordinate (const CameraSpacePoint& skeletonPoint)
488+ {
489+ ColorSpacePoint spacePoint; // Holds the mapped coordinate
490+ const auto & result = coordMapper->MapCameraPointToColorSpace (skeletonPoint, &spacePoint);
491+
492+ return SUCCEEDED (result) && !std::isnan (spacePoint.X ) && !std::isnan (spacePoint.Y )
493+ ? std::make_pair (spacePoint.X , spacePoint.Y ) // Send the mapped ones
494+ : std::make_pair (-1 , -1 ); // Unknown coordinates - fall back to default drawing
495+ }
496+
497+ private:
498+ DWORD size_in_bytes_ = 0 ;
499+ DWORD size_in_bytes_last_ = 0 ;
500+ BYTE* color_buffer_ = nullptr ;
501+
502+ BYTE* ResetBuffer (UINT size)
503+ {
504+ if (!color_buffer_ || size_in_bytes_ != size)
505+ {
506+ if (color_buffer_)
507+ {
508+ delete[] color_buffer_;
509+ color_buffer_ = nullptr ;
510+ }
511+
512+ if (0 != size)
513+ {
514+ color_buffer_ = new BYTE[size];
515+ }
516+ size_in_bytes_ = size;
517+ }
518+
519+ return color_buffer_;
520+ }
388521};
0 commit comments