#include <mil.h>
#include <Windows.h>
#include "KinectCameraInterface.h"
#define ARRAY_COUNT(x) (sizeof(x)/sizeof(x[0]))
static const MIL_INT KINECT_CAMERA_GRAB_TIMEOUT = 100;
CKinectCameraInterface::CKinectCameraInterface(MIL_ID MilSystem, BOOL ManualResetEvents)
:m_MilSystem(MilSystem),
m_MilProcThread(M_NULL),
m_MilGrabMutex(M_NULL),
m_StopProcEvent(NULL),
m_NextColorFrameEvent(NULL),
m_NextDepthFrameEvent(NULL)
{
m_StopProcEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
AllocNextFrameEvents(ManualResetEvents, &m_NextColorFrameEvent, &m_NextDepthFrameEvent);
MthrAlloc(MilSystem, M_MUTEX, M_DEFAULT, M_NULL, M_NULL, &m_MilGrabMutex);
}
void CKinectCameraInterface::AllocNextFrameEvents(BOOL ManualResetEvents, HANDLE* pNextColorFrameEvent, HANDLE* pNextDepthFrameEvent)
{
*pNextColorFrameEvent = CreateEvent(NULL, ManualResetEvents, FALSE, NULL);
*pNextDepthFrameEvent = CreateEvent(NULL, ManualResetEvents, FALSE, NULL);
}
CKinectCameraInterface::~CKinectCameraInterface()
{
CloseEvents(&m_NextColorFrameEvent, &m_NextDepthFrameEvent);
if(m_StopProcEvent)
{
CloseHandle(m_StopProcEvent);
m_StopProcEvent = NULL;
}
if(m_MilGrabMutex)
{
MthrFree(m_MilGrabMutex);
m_MilGrabMutex = M_NULL;
}
}
void CKinectCameraInterface::CloseEvents(HANDLE* pNextColorFrameEvent, HANDLE* pNextDepthFrameEvent)
{
if (*pNextColorFrameEvent)
{
CloseHandle(*pNextColorFrameEvent);
*pNextColorFrameEvent = NULL;
}
if (*pNextDepthFrameEvent)
{
CloseHandle(*pNextDepthFrameEvent);
*pNextDepthFrameEvent = NULL;
}
}
void CKinectCameraInterface::CloseDown()
{
StopGrab();
ShutdownCamera();
}
void CKinectCameraInterface::FrameGrabberProcess(MIL_INT Operation,
MIL_INT OperationFlag,
MIL_INT NbGrab ,
MIL_DIG_HOOK_FUNCTION_PTR HookHandlerPtr ,
void* UserDataPtr )
{
StopGrab();
if(Operation == M_STOP)
return;
MthrControl(m_MilGrabMutex, M_LOCK, M_DEFAULT);
m_HookHandlerPtr = HookHandlerPtr;
m_UserDataPtr = UserDataPtr;
m_NbGrab = (Operation != M_SEQUENCE || NbGrab == M_DEFAULT ) ? M_INFINITE : NbGrab;
MthrAlloc(m_MilSystem, M_THREAD, M_DEFAULT, GrabbingFunctionThread, this, &m_MilProcThread);
if(OperationFlag & M_SYNCHRONOUS)
MthrWait(m_MilProcThread, M_THREAD_END_WAIT, M_NULL);
MthrControl(m_MilGrabMutex, M_UNLOCK, M_DEFAULT);
}
MIL_UINT32 MFTYPE CKinectCameraInterface::GrabbingFunctionThread(void *UserDataPtr)
{
CKinectCameraInterface* pKinectCamera = (CKinectCameraInterface*) UserDataPtr;
pKinectCamera->GrabbingFunction();
return 1;
}
void CKinectCameraInterface::GrabbingFunction()
{
HANDLE Events[] = {m_StopProcEvent,
m_NextColorFrameEvent,
m_NextDepthFrameEvent};
int nEventIdx;
bool ContinueProcessing = true;
MIL_INT GrabCount = 0;
while (ContinueProcessing && (m_NbGrab == M_INFINITE || GrabCount < m_NbGrab))
{
nEventIdx = WaitForMultipleObjects(ARRAY_COUNT(Events), Events, FALSE, KINECT_CAMERA_GRAB_TIMEOUT);
switch (nEventIdx)
{
case WAIT_TIMEOUT:
continue;
case WAIT_OBJECT_0:
ContinueProcessing = false;
continue;
case WAIT_OBJECT_0 + 1:
ProcessKinectBufferColor(m_HookHandlerPtr, m_UserDataPtr);
GrabCount += m_NbGrab != M_INFINITE ? 1 : 0;
break;
case WAIT_OBJECT_0 + 2:
ProcessKinectBufferDepth(m_HookHandlerPtr, m_UserDataPtr);
break;
default:
break;
}
}
}
MIL_INT CKinectCameraInterface::StopGrab()
{
if(m_MilProcThread)
{
SetEvent(m_StopProcEvent);
MthrWait(m_MilProcThread, M_THREAD_END_WAIT, M_NULL);
MthrFree(m_MilProcThread);
m_MilProcThread = M_NULL;
}
return KINECT_CAMERA_OK;
}
void CKinectCameraInterface::ConvertKinectDepthToMilDepth(MIL_ID MilKinectDepthImage, MIL_ID MilDepthImage)
{
#if KINECT_CAMERA_VERSION == 1
MimShift(MilKinectDepthImage, MilDepthImage, -NUI_IMAGE_PLAYER_INDEX_SHIFT);
#else
MimFlip(MilKinectDepthImage, MilDepthImage, M_FLIP_HORIZONTAL, M_DEFAULT);
#endif
}
void CKinectCameraInterface::ConvertKinectColorToMilColor(MIL_ID MilKinectColorImage, MIL_ID MilColorImage)
{
#if KINECT_CAMERA_VERSION == 1
MbufCopy(MilKinectColorImage, MilColorImage);
#else
MimFlip(MilKinectColorImage, MilColorImage, M_FLIP_HORIZONTAL, M_DEFAULT);
#endif
}
MIL_ID CKinectCameraInterface::GetMilSystem() const
{
return m_MilSystem;
}