/**************************************************************************** * * * PrimeSense Sensor 5.x Alpha * * Copyright (C) 2011 PrimeSense Ltd. * * * * This file is part of PrimeSense Sensor. * * * * PrimeSense Sensor is free software: you can redistribute it and/or modify* * it under the terms of the GNU Lesser General Public License as published * * by the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * PrimeSense Sensor is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public License * * along with PrimeSense Sensor. If not, see .* * * ****************************************************************************/ //--------------------------------------------------------------------------- // Includes //--------------------------------------------------------------------------- #include "XnFileDevice.h" #include #include #include #include "XnDeviceFileReaderBC.h" #include #include //--------------------------------------------------------------------------- // Defines //--------------------------------------------------------------------------- #define XN_FILE_MAX_UNCOMPRESSED_DATA_SIZE (1600 * 1200 * sizeof(XnRGB24Pixel)) //--------------------------------------------------------------------------- // Types //--------------------------------------------------------------------------- typedef struct XnLastStreamData { XnUInt32 nPosition; XnUInt32 nFrameID; XnUInt64 nTimestamp; } XnLastStreamData; typedef XnStringsHashT XnLastStreamDataHash; //--------------------------------------------------------------------------- // XnFileDevice class //--------------------------------------------------------------------------- XnFileDevice::XnFileDevice(xn::Context& context, const XnChar* strInstanceName) : m_context(context), m_pInputStream(NULL), m_pDataPacker(NULL), m_pNotifications(NULL), m_pNotificationsCookie(NULL), m_bHighresTimestamps(FALSE), m_pStreamData(NULL), m_bFileHasData(FALSE), m_bNodeCollectionChanged(FALSE), m_nCurrTimestamp(0), m_pBCData(NULL), m_bRepeat(TRUE), m_bEOF(FALSE), m_strName(strInstanceName), m_hSelf(NULL) { xnOSMemSet(&m_ShiftToDepth, 0, sizeof(m_ShiftToDepth)); } XnFileDevice::~XnFileDevice() { Free(); } XnStatus XnFileDevice::Init() { XnStatus nRetVal = XN_STATUS_OK; nRetVal = XnStreamDataCreate(&m_pStreamData, "", XN_FILE_MAX_UNCOMPRESSED_DATA_SIZE); XN_IS_STATUS_OK(nRetVal); return (XN_STATUS_OK); } void XnFileDevice::Free() { for (XnNodeInfoMap::Iterator it = m_nodeInfoMap.Begin(); it != m_nodeInfoMap.End(); ++it) { XnNodeInfo& nodeInfo = it->Value(); XN_DELETE(nodeInfo.pXnCodec); if (nodeInfo.codec.IsValid()) { xnRemoveNeededNode(GetSelfNodeHandle(), nodeInfo.codec); nodeInfo.codec.Release(); } } m_nodeInfoMap.Clear(); if (m_ShiftToDepth.bIsInitialized) { XnShiftToDepthFree(&m_ShiftToDepth); } if (m_pInputStream != NULL) { XN_DELETE(m_pInputStream); m_pInputStream = NULL; } if (m_pDataPacker != NULL) { m_pDataPacker->Free(); XN_DELETE(m_pDataPacker); m_pDataPacker = NULL; } if (m_pStreamData != NULL) { XnStreamDataDestroy(&m_pStreamData); m_pStreamData = NULL; } } XnStatus XnFileDevice::ReadFileVersion() { XnStatus nRetVal = XN_STATUS_OK; // read magic from file XnChar csFileMagic[XN_DEVICE_FILE_MAGIC_LEN]; nRetVal = m_pInputStream->ReadData((XnUChar*)csFileMagic, XN_DEVICE_FILE_MAGIC_LEN); XN_IS_STATUS_OK(nRetVal); if (strncmp(csFileMagic, XN_DEVICE_FILE_MAGIC_V4, XN_DEVICE_FILE_MAGIC_LEN) == 0) { m_nFileVersion = 4; } else if (strncmp(csFileMagic, XN_DEVICE_FILE_MAGIC_V3, XN_DEVICE_FILE_MAGIC_LEN) == 0) { m_nFileVersion = 3; } else if (strncmp(csFileMagic, XN_DEVICE_FILE_MAGIC_V2, XN_DEVICE_FILE_MAGIC_LEN) == 0) { m_nFileVersion = 2; } else if (strncmp(csFileMagic, XN_DEVICE_FILE_MAGIC_V1, XN_DEVICE_FILE_MAGIC_LEN) == 0) { m_nFileVersion = 1; } else { XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_FILE_CORRUPTED, XN_MASK_FILE, "Invalid file magic!"); } return (XN_STATUS_OK); } XnStatus XnFileDevice::ReadInitialState(XnPropertySet* pSet) { XnStatus nRetVal = XN_STATUS_OK; if (m_nFileVersion < 4) { if (m_pBCData == NULL) { nRetVal = BCInit(); XN_IS_STATUS_OK(nRetVal); } return BCReadInitialState(pSet); } // read an object from data packer XnPackedDataType nType; nRetVal = m_pDataPacker->ReadNextObject(&nType); XN_IS_STATUS_OK(nRetVal); if (nType != XN_PACKED_PROPERTY_SET) { XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_FILE_CORRUPTED, XN_MASK_DDK, "Stream does not start with a property set!"); } nRetVal = m_pDataPacker->ReadPropertySet(pSet); XN_IS_STATUS_OK(nRetVal); return (XN_STATUS_OK); } XnStatus XnFileDevice::SetInitialState(XnPropertySet* pSet) { XnStatus nRetVal = XN_STATUS_OK; // Fix state (remove some properties that we don't wish to reflect in reader device) XnActualPropertiesHash* pDeviceModule = NULL; if (XN_STATUS_OK == pSet->pData->Get(XN_MODULE_NAME_DEVICE, pDeviceModule)) { pDeviceModule->Remove(XN_MODULE_PROPERTY_READ_WRITE_MODE); pDeviceModule->Remove(XN_MODULE_PROPERTY_PRIMARY_STREAM); // check for timestamps resolution XnActualIntProperty* pIntProp = NULL; if (XN_STATUS_OK == pDeviceModule->Get(XN_MODULE_PROPERTY_HIGH_RES_TIMESTAMPS, (XnProperty*&)pIntProp)) { m_bHighresTimestamps = (pIntProp->GetValue() == TRUE); } } // TODO: create DEVICE node // now create the rest of the modules and streams (DEVICE was already created) XnPropertySetData* pPropSetData = pSet->pData; for (XnPropertySetData::ConstIterator it = pPropSetData->Begin(); it != pPropSetData->End(); ++it) { // ignore module DEVICE if (strcmp(XN_MODULE_NAME_DEVICE, it->Key()) == 0) { continue; } // check if this is a stream XnActualPropertiesHash::ConstIterator itProp = it->Value()->End(); if (XN_STATUS_OK == it->Value()->Find(XN_STREAM_PROPERTY_TYPE, itProp)) { XnActualStringProperty* pTypeProp = (XnActualStringProperty*)itProp->Value(); nRetVal = HandleNewStream(pTypeProp->GetValue(), it->Key(), it->Value()); XN_IS_STATUS_OK(nRetVal); } } // modules loop return (XN_STATUS_OK); } XnStatus XnFileDevice::SetInputStream(void *pStreamCookie, XnPlayerInputStreamInterface *pStream) { XnStatus nRetVal = XN_STATUS_OK; XN_VALIDATE_NEW(m_pInputStream, XnInputStream, pStream, pStreamCookie); nRetVal = m_pInputStream->Init(); if (nRetVal != XN_STATUS_OK) { XN_DELETE(m_pInputStream); m_pInputStream = NULL; return (nRetVal); } // read format version nRetVal = ReadFileVersion(); XN_IS_STATUS_OK(nRetVal); m_pDataPacker = XN_NEW(XnDataPacker, m_pInputStream, XN_DEVICE_FILE_MAX_INTERNAL_BUFFER); if (m_pDataPacker == NULL) { XN_DELETE(m_pInputStream); return (XN_STATUS_ALLOC_FAILED); } nRetVal = m_pDataPacker->Init(); if (nRetVal != XN_STATUS_OK) { XN_DELETE(m_pDataPacker); XN_DELETE(m_pInputStream); return (nRetVal); } // read initial state XN_PROPERTY_SET_CREATE_ON_STACK(props); nRetVal = ReadInitialState(&props); XN_IS_STATUS_OK(nRetVal); nRetVal = SetInitialState(&props); XN_IS_STATUS_OK(nRetVal); // now read till first data XnBool bWrap; nRetVal = ReadTillNextData(&bWrap); XN_IS_STATUS_OK(nRetVal); return (XN_STATUS_OK); } XnStatus XnFileDevice::SetNodeNotifications(void *pNodeNotificationsCookie, XnNodeNotifications *pNodeNotifications) { m_pNotifications = pNodeNotifications; m_pNotificationsCookie = pNodeNotificationsCookie; return (XN_STATUS_OK); } XnStatus XnFileDevice::SetRepeat(XnBool bRepeat) { m_bRepeat = bRepeat; return (XN_STATUS_OK); } XnStatus XnFileDevice::SeekTo(XnUInt64 nMinTimestamp, const XnChar* strNodeName, XnUInt32 nMinFrameID) { XnStatus nRetVal = XN_STATUS_OK; // first check if we need to seek forward or backwards (even if we're in the correct location, // we need to rewind, so that next read will return this frame again). XnNodeInfo* pNodeInfo = NULL; if (strNodeName != NULL) { nRetVal = m_nodeInfoMap.Get(strNodeName, pNodeInfo); XN_IS_STATUS_OK(nRetVal); if (nMinFrameID <= pNodeInfo->nCurrFrameID) { nRetVal = Rewind(); XN_IS_STATUS_OK(nRetVal); } } else { if (nMinTimestamp <= m_nCurrTimestamp) { nRetVal = Rewind(); XN_IS_STATUS_OK(nRetVal); } } XnBool bFoundNewData = FALSE; // Keep current position. XnUInt32 nStartingPosition; nRetVal = m_pInputStream->Tell(&nStartingPosition); XN_IS_STATUS_OK(nRetVal); // start seeking forward until point is reached. XnUInt32 nFoundPosition; XnPackedDataType nType = (XnPackedDataType)-1; XnLastStreamDataHash StreamsHash; for (;;) { XnUInt32 nPositionBefore; nRetVal = m_pInputStream->Tell(&nPositionBefore); XN_IS_STATUS_OK(nRetVal); nRetVal = m_pDataPacker->ReadNextObject(&nType); XN_IS_STATUS_OK(nRetVal); XnUInt32 nPositionAfter; nRetVal = m_pInputStream->Tell(&nPositionAfter); XN_IS_STATUS_OK(nRetVal); if (nType == XN_PACKED_STREAM_DATA) { bFoundNewData = TRUE; XnStreamData props; XnCompressionFormats nCompression; XnUInt32 nCompressedSize; nRetVal = m_pDataPacker->ReadStreamDataProps(&props, &nCompression, &nCompressedSize); XN_IS_STATUS_OK(nRetVal); XnLastStreamData data; if (XN_STATUS_OK != StreamsHash.Get(props.StreamName, data)) { XnNodeInfo* pNodeInfo = NULL; nRetVal = m_nodeInfoMap.Get(props.StreamName, pNodeInfo); XN_IS_STATUS_OK(nRetVal); data.nFrameID = pNodeInfo->nCurrFrameID + 1; } else { // if we had previous data from this stream, ignore it m_PositionsToIgnore.Set(data.nPosition, 0); ++data.nFrameID; } data.nPosition = nPositionAfter; data.nTimestamp = props.nTimestamp; nRetVal = StreamsHash.Set(props.StreamName, data); XN_IS_STATUS_OK(nRetVal); // now check if condition is met if (strNodeName != NULL) { if (strcmp(strNodeName, props.StreamName) == 0 && data.nFrameID >= nMinFrameID) { // keep this position (we'll read up till here). nFoundPosition = nPositionAfter; break; } } else if (data.nTimestamp >= nMinTimestamp) { // keep this position (we'll read up till here). nFoundPosition = nPositionAfter; break; } } else if (nType == XN_PACKED_END) { // we'll read up to the last data of each stream nFoundPosition = nPositionBefore; break; } } // now seek back nRetVal = m_pInputStream->Seek(nStartingPosition); XN_IS_STATUS_OK(nRetVal); if (bFoundNewData) { // read everything up to position XnUInt32 nPositionAfter = nStartingPosition; while (nPositionAfter < nFoundPosition) { nRetVal = ReadNextEventFromStream(&nType); XN_IS_STATUS_OK(nRetVal); nRetVal = m_pInputStream->Tell(&nPositionAfter); XN_IS_STATUS_OK(nRetVal); } } else { /* // just remark the data as new (this is last frame, return it again to user) XnDeviceModuleHolderList streams; nRetVal = GetStreamsList(streams); XN_IS_STATUS_OK(nRetVal); for (XnDeviceModuleHolderList::Iterator it = streams.Begin(); it != streams.End(); ++it) { XnStreamReaderStream* pStream = (XnStreamReaderStream*)(*it)->GetModule(); pStream->ReMarkDataAsNew(); } */ } return (XN_STATUS_OK); } XnStatus XnFileDevice::SeekToTimeStamp(XnInt64 nTimeOffset, XnPlayerSeekOrigin origin) { XnUInt64 nTimestamp = 0; if (origin == XN_PLAYER_SEEK_CUR) { nTimestamp = m_nCurrTimestamp + nTimeOffset; } else if (origin == XN_PLAYER_SEEK_SET) { nTimestamp = nTimeOffset; } else { // TODO: find max timestamp and add offset return XN_STATUS_NOT_IMPLEMENTED; } xnLogInfo(XN_MASK_FILE, "Seeking file to timestamp %llu...", nTimestamp); if (m_nFileVersion < 4) { return BCSeek(nTimestamp); } else { return SeekTo(nTimestamp, NULL, 0); } } XnStatus XnFileDevice::SeekToFrame(const XnChar* strNodeName, XnInt32 nFrameOffset, XnPlayerSeekOrigin origin) { XnStatus nRetVal = XN_STATUS_OK; XnNodeInfo* pNodeInfo = NULL; nRetVal = m_nodeInfoMap.Get(strNodeName, pNodeInfo); XN_IS_STATUS_OK(nRetVal); XnInt32 nFrameID = 0; switch (origin) { case XN_PLAYER_SEEK_CUR: nFrameID = pNodeInfo->nCurrFrameID + nFrameOffset; break; case XN_PLAYER_SEEK_SET: nFrameID = nFrameOffset; break; case XN_PLAYER_SEEK_END: // TODO: handle return XN_STATUS_NOT_IMPLEMENTED; } // don't allow seeking to frame 0 nFrameID = XN_MAX(nFrameID, 1); xnLogInfo(XN_MASK_FILE, "Seeking file to frameID %u of node %s...", nFrameID, strNodeName); if (m_nFileVersion < 4) { return BCSeekFrame(nFrameID); } else { nRetVal = SeekTo(0, strNodeName, nFrameID); XN_IS_STATUS_OK(nRetVal); } return (XN_STATUS_OK); } XnStatus XnFileDevice::TellTimestamp(XnUInt64& nTimestamp) { nTimestamp = m_nCurrTimestamp; return (XN_STATUS_OK); } XnStatus XnFileDevice::TellFrame(const XnChar* strNodeName, XnUInt32 &nFrameOffset) { XnStatus nRetVal = XN_STATUS_OK; XnNodeInfo* pNodeInfo = NULL; nRetVal = m_nodeInfoMap.Get(strNodeName, pNodeInfo); XN_IS_STATUS_OK(nRetVal); nFrameOffset = pNodeInfo->nCurrFrameID; return (XN_STATUS_OK); } XnStatus XnFileDevice::GetNumFrames(const XnChar* strNodeName, XnUInt32& nFrames) { XnStatus nRetVal = XN_STATUS_OK; xn::ProductionNode node; nRetVal = m_context.GetProductionNodeByName(strNodeName, node); XN_IS_STATUS_OK(nRetVal); XnUInt64 nFrames64 = 0; nRetVal = node.GetIntProperty(XN_STREAM_PROPERTY_NUMBER_OF_FRAMES, nFrames64); XN_IS_STATUS_OK(nRetVal); nFrames = (XnUInt32)nFrames64; return XN_STATUS_OK; } XnBool XnFileDevice::IsEOF() { return m_bEOF; } XnStatus XnFileDevice::RegisterToEndOfFileReached(XnModuleStateChangedHandler handler, void* pCookie, XnCallbackHandle& hCallback) { return m_eofEvent.Register(handler, pCookie, hCallback); } void XnFileDevice::UnregisterFromEndOfFileReached(XnCallbackHandle hCallback) { m_eofEvent.Unregister(hCallback); } XnStatus XnFileDevice::ReadNext() { XnStatus nRetVal = XN_STATUS_OK; XnBool bWrap; nRetVal = ReadTillNextData(&bWrap); XN_IS_STATUS_OK(nRetVal); return (XN_STATUS_OK); } XnStatus XnFileDevice::HandlePackedObject(XnPackedDataType nObjectType) { XnStatus nRetVal = XN_STATUS_OK; switch (nObjectType) { case XN_PACKED_NEW_STREAM: nRetVal = ReadNewStream(); XN_IS_STATUS_OK(nRetVal); break; case XN_PACKED_STREAM_REMOVED: nRetVal = ReadStreamRemoved(); XN_IS_STATUS_OK(nRetVal); break; case XN_PACKED_INT_PROPERTY: nRetVal = ReadIntProperty(); XN_IS_STATUS_OK(nRetVal); break; case XN_PACKED_REAL_PROPERTY: nRetVal = ReadRealProperty(); XN_IS_STATUS_OK(nRetVal); break; case XN_PACKED_STRING_PROPERTY: nRetVal = ReadStringProperty(); XN_IS_STATUS_OK(nRetVal); break; case XN_PACKED_GENERAL_PROPERTY: nRetVal = ReadGeneralProperty(); XN_IS_STATUS_OK(nRetVal); break; case XN_PACKED_STREAM_DATA: nRetVal = ReadStreamData(); XN_IS_STATUS_OK(nRetVal); break; case XN_PACKED_END: nRetVal = HandleEndOfStream(); XN_IS_STATUS_OK(nRetVal); break; default: XN_LOG_WARNING_RETURN(XN_STATUS_DEVICE_FILE_CORRUPTED, XN_MASK_DDK, "Unexpected packed type: %d", nObjectType); } return (XN_STATUS_OK); } XnStatus XnFileDevice::ReadNewStream() { XnStatus nRetVal = XN_STATUS_OK; XnChar strType[XN_DEVICE_MAX_STRING_LENGTH]; XnChar strName[XN_DEVICE_MAX_STRING_LENGTH]; // create property set XnPropertySet* pPropertySet = NULL; nRetVal = XnPropertySetCreate(&pPropertySet); XN_IS_STATUS_OK(nRetVal); // read from stream nRetVal = m_pDataPacker->ReadNewStream(strType, strName, pPropertySet); if (nRetVal == XN_STATUS_OK) { // create it nRetVal = HandleNewStream(strType, strName, pPropertySet->pData->Begin()->Value()); } XnPropertySetDestroy(&pPropertySet); return (nRetVal); } XnProductionNodeType GetNodeType(const XnChar* strType) { if (strcmp(strType, XN_STREAM_TYPE_DEPTH) == 0) { return XN_NODE_TYPE_DEPTH; } else if (strcmp(strType, XN_STREAM_TYPE_IMAGE) == 0) { return XN_NODE_TYPE_IMAGE; } else if (strcmp(strType, XN_STREAM_TYPE_IR) == 0) { return XN_NODE_TYPE_IR; } else if (strcmp(strType, XN_STREAM_TYPE_AUDIO) == 0) { return XN_NODE_TYPE_AUDIO; } else { XN_ASSERT(FALSE); return (XnProductionNodeType)-1; } } XnStatus XnFileDevice::HandleNewStream(const XnChar *strType, const XnChar *strName, const XnActualPropertiesHash *pInitialValues) { XnStatus nRetVal = XN_STATUS_OK; // check if we need to ignore that (stream was not removed upon Rewind). XnNodeInfoMap::Iterator it = m_ignoreNewNodes.End(); if (m_ignoreNewNodes.Find(strName, it) == XN_STATUS_OK) { // ignore return (XN_STATUS_OK); } XnProductionNodeType type = GetNodeType(strType); if (type == -1) { XN_LOG_WARNING_RETURN(XN_STATUS_CORRUPT_FILE, XN_MASK_FILE, "Invalid node type: %s", strType); } // find compression type XnActualIntProperty* pComp = NULL; nRetVal = pInitialValues->Get(XN_STREAM_PROPERTY_COMPRESSION, (XnProperty*&)pComp); XN_IS_STATUS_OK(nRetVal); XnCodecID codecID = XnCodec::GetCodecIDFromCompressionFormat((XnCompressionFormats)pComp->GetValue()); if (codecID == XN_CODEC_NULL) { XN_LOG_WARNING_RETURN(XN_STATUS_CORRUPT_FILE, XN_MASK_FILE, "Invalid compression type: %llu", pComp->GetValue()); } // notify we have a new node nRetVal = m_pNotifications->OnNodeAdded(m_pNotificationsCookie, strName, type, codecID); XN_IS_STATUS_OK(nRetVal); // we support the mirror capability nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strName, XN_CAPABILITY_MIRROR, 1); XN_IS_STATUS_OK(nRetVal); // we support the extended serialization capability nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strName, XN_CAPABILITY_EXTENDED_SERIALIZATION, 1); XN_IS_STATUS_OK(nRetVal); // now write state for (XnActualPropertiesHash::ConstIterator it = pInitialValues->Begin(); it != pInitialValues->End(); ++it) { XnProperty* pProp = it->Value(); switch (pProp->GetType()) { case XN_PROPERTY_TYPE_INTEGER: { XnActualIntProperty* pIntProp = (XnActualIntProperty*)pProp; nRetVal = HandleIntProperty(strName, pProp->GetName(), pIntProp->GetValue()); } break; case XN_PROPERTY_TYPE_REAL: { XnActualRealProperty* pRealProp = (XnActualRealProperty*)pProp; nRetVal = HandleRealProperty(strName, pProp->GetName(), pRealProp->GetValue()); } break; case XN_PROPERTY_TYPE_STRING: { XnActualStringProperty* pStrProp = (XnActualStringProperty*)pProp; nRetVal = HandleStringProperty(strName, pProp->GetName(), pStrProp->GetValue()); } break; case XN_PROPERTY_TYPE_GENERAL: { XnActualGeneralProperty* pGenProp = (XnActualGeneralProperty*)pProp; nRetVal = HandleGeneralProperty(strName, pProp->GetName(), pGenProp->GetValue()); } break; default: XN_LOG_WARNING_RETURN(XN_STATUS_ERROR, XN_MASK_FILE, "Unknown property type: %d", pProp->GetType()); } XN_IS_STATUS_OK(nRetVal); } // at this stage, a node should exist with this name xn::ProductionNode node; nRetVal = m_context.GetProductionNodeByName(strName, node); XN_IS_STATUS_OK(nRetVal); // S2D & RW if (type == XN_NODE_TYPE_DEPTH) { nRetVal = UpdateS2DTables(xn::DepthGenerator(node)); XN_IS_STATUS_OK(nRetVal); nRetVal = UpdateRWData(xn::DepthGenerator(node)); XN_IS_STATUS_OK(nRetVal); } // notify end-of-state nRetVal = m_pNotifications->OnNodeStateReady(m_pNotificationsCookie, strName); XN_IS_STATUS_OK(nRetVal); // add it to the map XnNodeInfo nodeInfo = {0}; nRetVal = m_nodeInfoMap.Set(strName, nodeInfo); XN_IS_STATUS_OK(nRetVal); // create codec nRetVal = CreateCodec(node); XN_IS_STATUS_OK(nRetVal); // check IR compatibility nRetVal = CheckIRCompatibility(node); XN_IS_STATUS_OK(nRetVal); return (XN_STATUS_OK); } XnStatus XnFileDevice::CreateCodec(xn::ProductionNode& node) { XnStatus nRetVal = XN_STATUS_OK; XnNodeInfo* pNodeInfo = NULL; if (m_nodeInfoMap.Get(node.GetName(), pNodeInfo) == XN_STATUS_OK) { XnUInt64 nValue; nRetVal = node.GetIntProperty(XN_STREAM_PROPERTY_COMPRESSION, nValue); XN_IS_STATUS_OK(nRetVal); // create new one XnCodecID codecID = XnCodec::GetCodecIDFromCompressionFormat((XnCompressionFormats)nValue); if (codecID == XN_CODEC_NULL) { XN_LOG_WARNING_RETURN(XN_STATUS_CORRUPT_FILE, XN_MASK_FILE, "Invalid compression type: %llu", nValue); } if (pNodeInfo->pXnCodec == NULL || pNodeInfo->pXnCodec->GetCompressionFormat() != nValue) { // release old codec XN_DELETE(pNodeInfo->pXnCodec); if (pNodeInfo->codec.IsValid()) { xnRemoveNeededNode(GetSelfNodeHandle(), pNodeInfo->codec); pNodeInfo->codec.Release(); } // special case: IR recorded with JPEG. This mode is no longer allowed by OpenNI (JPEG // can now only be used for image). We'll have to handle it ourselves. if (node.GetInfo().GetDescription().Type == XN_NODE_TYPE_IR && codecID == XN_CODEC_JPEG) { xn::IRGenerator irGen(node); XnMapOutputMode outputMode; nRetVal = irGen.GetMapOutputMode(outputMode); XN_IS_STATUS_OK(nRetVal); XN_VALIDATE_NEW_AND_INIT(pNodeInfo->pXnCodec, XnJpegCodec, TRUE, outputMode.nXRes, outputMode.nYRes); } else { // normal case nRetVal = m_context.CreateCodec(codecID, node, pNodeInfo->codec); XN_IS_STATUS_OK(nRetVal); // we need to make the codec a needed node, so that if xnForceShutdown() is called, we will be // destroyed *before* it does (as we hold a reference to it). nRetVal = xnAddNeededNode(GetSelfNodeHandle(), pNodeInfo->codec); XN_IS_STATUS_OK(nRetVal); XN_VALIDATE_NEW(pNodeInfo->pXnCodec, XnNiCodec, pNodeInfo->codec); } } } return (XN_STATUS_OK); } XnStatus XnFileDevice::CheckIRCompatibility(xn::ProductionNode& node) { XnStatus nRetVal = XN_STATUS_OK; XnNodeInfo* pNodeInfo = NULL; if (node.GetInfo().GetDescription().Type == XN_NODE_TYPE_IR && m_nodeInfoMap.Get(node.GetName(), pNodeInfo) == XN_STATUS_OK) { XnUInt64 nValue; nRetVal = node.GetIntProperty(XN_STREAM_PROPERTY_OUTPUT_FORMAT, nValue); XN_IS_STATUS_OK(nRetVal); pNodeInfo->bIRisRGB = (nValue == XN_OUTPUT_FORMAT_RGB24); } return (XN_STATUS_OK); } XnStatus XnFileDevice::ReadStreamRemoved() { XnStatus nRetVal = XN_STATUS_OK; // read stream name XnChar strName[XN_DEVICE_MAX_STRING_LENGTH]; nRetVal = m_pDataPacker->ReadStreamRemoved(strName); XN_IS_STATUS_OK(nRetVal); // remove it nRetVal = HandleStreamRemoved(strName); XN_IS_STATUS_OK(nRetVal); return (XN_STATUS_OK); } XnStatus XnFileDevice::HandleStreamRemoved(const XnChar* strName) { XnStatus nRetVal = XN_STATUS_OK; // check for specific case: all streams are removed and then end-of-file is reached. // in this case, we don't really want to destroy streams, just wrap around. XnStringsSet StreamsToRemove; nRetVal = StreamsToRemove.Set(strName); XN_IS_STATUS_OK(nRetVal); XnPackedDataType nType = XN_PACKED_STREAM_REMOVED; XnUInt32 nPositionBefore; for (;;) { nRetVal = m_pInputStream->Tell(&nPositionBefore); XN_IS_STATUS_OK(nRetVal); nRetVal = m_pDataPacker->ReadNextObject(&nType); XN_IS_STATUS_OK(nRetVal); if (nType == XN_PACKED_STREAM_REMOVED) { XnChar strTempName[XN_DEVICE_MAX_STRING_LENGTH]; nRetVal = m_pDataPacker->ReadStreamRemoved(strTempName); XN_IS_STATUS_OK(nRetVal); nRetVal = StreamsToRemove.Set(strTempName); XN_IS_STATUS_OK(nRetVal); } else { break; } } if (nType != XN_PACKED_END) { // Not the case we were looking for. Remove those streams. for (XnStringsSet::Iterator it = StreamsToRemove.Begin(); it != StreamsToRemove.End(); ++it) { nRetVal = m_pNotifications->OnNodeRemoved(m_pNotificationsCookie, it->Key()); XN_IS_STATUS_OK(nRetVal); XnNodeInfo* pNodeInfo = NULL; m_nodeInfoMap.Get(it->Key(), pNodeInfo); XN_DELETE(pNodeInfo->pXnCodec); m_nodeInfoMap.Remove(it->Key()); m_ignoreNewNodes.Remove(it->Key()); } m_bNodeCollectionChanged = TRUE; } // in any case, the last object we read wasn't handled yet (end-of-stream or another event), so // seek back, so it will be handled. nRetVal = m_pInputStream->Seek(nPositionBefore); XN_IS_STATUS_OK(nRetVal); return (XN_STATUS_OK); } XnStatus XnFileDevice::ReadIntProperty() { XnStatus nRetVal = XN_STATUS_OK; XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; XnUInt64 nValue; // read change data nRetVal = m_pDataPacker->ReadProperty(strModule, strProp, &nValue); XN_IS_STATUS_OK(nRetVal); nRetVal = HandleIntProperty(strModule, strProp, nValue); XN_IS_STATUS_OK(nRetVal); return (XN_STATUS_OK); } XnStatus XnFileDevice::HandleIntProperty(const XnChar *strModule, const XnChar *strName, XnUInt64 nValue) { XnStatus nRetVal = XN_STATUS_OK; // ignore some properties if (strcmp(strModule, XN_MODULE_NAME_DEVICE) == 0 && strcmp(strName, XN_MODULE_PROPERTY_PRIMARY_STREAM) == 0) { return (XN_STATUS_OK); } // OpenNI props if (strcmp(strName, XN_STREAM_PROPERTY_STATE) == 0) { nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, XN_PROP_IS_GENERATING, nValue); } else if (strcmp(strName, XN_MODULE_PROPERTY_MIRROR) == 0) { nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, XN_PROP_MIRROR, nValue); } else if (strcmp(strName, XN_STREAM_PROPERTY_X_RES) == 0 || strcmp(strName, XN_STREAM_PROPERTY_Y_RES) == 0 || strcmp(strName, XN_STREAM_PROPERTY_FPS) == 0) { xn::MapGenerator node; nRetVal = m_context.GetProductionNodeByName(strModule, node); XN_IS_STATUS_OK(nRetVal); XnMapOutputMode mode; nRetVal = node.GetMapOutputMode(mode); XN_IS_STATUS_OK(nRetVal); if (strcmp(strName, XN_STREAM_PROPERTY_X_RES) == 0) { mode.nXRes = (XnUInt32)nValue; } else if (strcmp(strName, XN_STREAM_PROPERTY_Y_RES) == 0) { mode.nYRes = (XnUInt32)nValue; } else if (strcmp(strName, XN_STREAM_PROPERTY_FPS) == 0) { mode.nFPS = (XnUInt32)nValue; } // change supported modes to this one nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, XN_PROP_SUPPORTED_MAP_OUTPUT_MODES_COUNT, 1); XN_IS_STATUS_OK(nRetVal); nRetVal = m_pNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie, strModule, XN_PROP_SUPPORTED_MAP_OUTPUT_MODES, sizeof(XnMapOutputMode), &mode); XN_IS_STATUS_OK(nRetVal); // and set actual mode nRetVal = m_pNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie, strModule, XN_PROP_MAP_OUTPUT_MODE, sizeof(mode), &mode); XN_IS_STATUS_OK(nRetVal); } else if (strcmp(strName, XN_STREAM_PROPERTY_OUTPUT_FORMAT) == 0) { switch (nValue) { case XN_OUTPUT_FORMAT_SHIFT_VALUES: case XN_OUTPUT_FORMAT_DEPTH_VALUES: case XN_OUTPUT_FORMAT_GRAYSCALE16: case XN_OUTPUT_FORMAT_PCM: break; case XN_OUTPUT_FORMAT_GRAYSCALE8: nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, XN_PROP_PIXEL_FORMAT, XN_PIXEL_FORMAT_GRAYSCALE_8_BIT); break; case XN_OUTPUT_FORMAT_RGB24: nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, XN_PROP_PIXEL_FORMAT, XN_PIXEL_FORMAT_RGB24); break; case XN_OUTPUT_FORMAT_YUV422: nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, XN_PROP_PIXEL_FORMAT, XN_PIXEL_FORMAT_YUV422); break; default: XN_ASSERT(FALSE); return XN_STATUS_ERROR; } XN_IS_STATUS_OK(nRetVal); // also set property (we need it for IR compatibility) nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, strName, nValue); } else if (strcmp(strName, XN_STREAM_PROPERTY_DEVICE_MAX_DEPTH) == 0) { nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, XN_PROP_DEVICE_MAX_DEPTH, nValue); } else if (strcmp(strName, XN_STREAM_PROPERTY_SAMPLE_RATE) == 0 || strcmp(strName, XN_STREAM_PROPERTY_NUMBER_OF_CHANNELS) == 0) { xn::AudioGenerator node; nRetVal = m_context.GetProductionNodeByName(strModule, node); XN_IS_STATUS_OK(nRetVal); XnWaveOutputMode mode; nRetVal = node.GetWaveOutputMode(mode); XN_IS_STATUS_OK(nRetVal); if (strcmp(strName, XN_STREAM_PROPERTY_SAMPLE_RATE) == 0) { mode.nSampleRate = (XnUInt32)nValue; } else if (strcmp(strName, XN_STREAM_PROPERTY_NUMBER_OF_CHANNELS) == 0) { mode.nChannels = (XnUInt8)nValue; } // change supported modes to this one nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, XN_PROP_WAVE_SUPPORTED_OUTPUT_MODES_COUNT, 1); XN_IS_STATUS_OK(nRetVal); nRetVal = m_pNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie, strModule, XN_PROP_WAVE_SUPPORTED_OUTPUT_MODES, sizeof(XnWaveOutputMode), &mode); XN_IS_STATUS_OK(nRetVal); // and set actual mode nRetVal = m_pNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie, strModule, XN_PROP_WAVE_OUTPUT_MODE, sizeof(mode), &mode); XN_IS_STATUS_OK(nRetVal); } else { nRetVal = m_pNotifications->OnNodeIntPropChanged(m_pNotificationsCookie, strModule, strName, nValue); } XN_IS_STATUS_OK(nRetVal); /********************/ // Now for some additional logic... /********************/ xn::ProductionNode node; nRetVal = m_context.GetProductionNodeByName(strModule, node); XN_IS_STATUS_OK(nRetVal); // replace codec? if (strcmp(strName, XN_STREAM_PROPERTY_COMPRESSION) == 0) { nRetVal = CreateCodec(node); XN_IS_STATUS_OK(nRetVal); } else if (strcmp(strName, XN_STREAM_PROPERTY_OUTPUT_FORMAT) == 0) { nRetVal = CheckIRCompatibility(node); XN_IS_STATUS_OK(nRetVal); } else if (strcmp(strModule, XN_MODULE_NAME_DEVICE) == 0 && strcmp(strName, XN_MODULE_PROPERTY_HIGH_RES_TIMESTAMPS) == 0) { // check timestamps resolution m_bHighresTimestamps = (nValue == TRUE); } else if (strcmp(strName, XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE) == 0 || strcmp(strName, XN_STREAM_PROPERTY_MAX_SHIFT) == 0 || strcmp(strName, XN_STREAM_PROPERTY_DEVICE_MAX_DEPTH) == 0 || strcmp(strName, XN_STREAM_PROPERTY_CONST_SHIFT) == 0 || strcmp(strName, XN_STREAM_PROPERTY_PIXEL_SIZE_FACTOR) == 0 || strcmp(strName, XN_STREAM_PROPERTY_PARAM_COEFF) == 0 || strcmp(strName, XN_STREAM_PROPERTY_SHIFT_SCALE) == 0) { // only after node is ready xn::DepthGenerator depth(node); XnNodeInfo* pNodeInfo = NULL; if (m_nodeInfoMap.Get(strModule, pNodeInfo) == XN_STATUS_OK && m_context.GetProductionNodeByName(strModule, depth) == XN_STATUS_OK) { nRetVal = UpdateS2DTables(depth); XN_IS_STATUS_OK(nRetVal); } } if (strcmp(strName, XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE) == 0 || strcmp(strName, XN_STREAM_PROPERTY_X_RES) == 0) { // only after node is ready XnNodeInfo* pNodeInfo; if (m_nodeInfoMap.Get(strModule, pNodeInfo) == XN_STATUS_OK) { // check this is a depth node if (node.GetInfo().GetDescription().Type == XN_NODE_TYPE_DEPTH) { xn::DepthGenerator depth(node); nRetVal = UpdateRWData(depth); XN_IS_STATUS_OK(nRetVal); } } } return (XN_STATUS_OK); } XnStatus XnFileDevice::ReadRealProperty() { XnStatus nRetVal = XN_STATUS_OK; XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; XnDouble dValue; // read change data nRetVal = m_pDataPacker->ReadProperty(strModule, strProp, &dValue); XN_IS_STATUS_OK(nRetVal); nRetVal = HandleRealProperty(strModule, strProp, dValue); XN_IS_STATUS_OK(nRetVal); return (XN_STATUS_OK); } XnStatus XnFileDevice::HandleRealProperty(const XnChar *strModule, const XnChar *strName, XnDouble dValue) { XnStatus nRetVal = XN_STATUS_OK; nRetVal = m_pNotifications->OnNodeRealPropChanged(m_pNotificationsCookie, strModule, strName, dValue); XN_IS_STATUS_OK(nRetVal); XnNodeInfo* pNodeInfo = NULL; if (strcmp(strName, XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE) == 0 || strcmp(strName, XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE) == 0) { // only after node is ready xn::DepthGenerator depth; if (m_nodeInfoMap.Get(strModule, pNodeInfo) == XN_STATUS_OK && m_context.GetProductionNodeByName(strModule, depth) == XN_STATUS_OK) { nRetVal = UpdateS2DTables(depth); XN_IS_STATUS_OK(nRetVal); } } if (strcmp(strName, XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE) == 0) { // only after node is ready xn::DepthGenerator depth; if (m_nodeInfoMap.Get(strModule, pNodeInfo) == XN_STATUS_OK && m_context.GetProductionNodeByName(strModule, depth) == XN_STATUS_OK) { nRetVal = UpdateRWData(depth); XN_IS_STATUS_OK(nRetVal); } } return (XN_STATUS_OK); } XnStatus XnFileDevice::ReadStringProperty() { XnStatus nRetVal = XN_STATUS_OK; XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; XnChar strValue[XN_DEVICE_MAX_STRING_LENGTH]; // read change data nRetVal = m_pDataPacker->ReadProperty(strModule, strProp, strValue); XN_IS_STATUS_OK(nRetVal); nRetVal = HandleStringProperty(strModule, strProp, strValue); XN_IS_STATUS_OK(nRetVal); return (XN_STATUS_OK); } XnStatus XnFileDevice::HandleStringProperty(const XnChar *strModule, const XnChar *strName, const XnChar* strValue) { XnStatus nRetVal = XN_STATUS_OK; nRetVal = m_pNotifications->OnNodeStringPropChanged(m_pNotificationsCookie, strModule, strName, strValue); XN_IS_STATUS_OK(nRetVal); return (XN_STATUS_OK); } XnStatus XnFileDevice::ReadGeneralProperty() { XnStatus nRetVal = XN_STATUS_OK; XnChar strModule[XN_DEVICE_MAX_STRING_LENGTH]; XnChar strProp[XN_DEVICE_MAX_STRING_LENGTH]; XnGeneralBuffer gbValue; // read change data nRetVal = m_pDataPacker->ReadProperty(strModule, strProp, &gbValue); XN_IS_STATUS_OK(nRetVal); nRetVal = HandleGeneralProperty(strModule, strProp, gbValue); XN_IS_STATUS_OK(nRetVal); return (XN_STATUS_OK); } XnStatus XnFileDevice::HandleGeneralProperty(const XnChar* strModule, const XnChar* strName, const XnGeneralBuffer& gbValue) { XnStatus nRetVal = XN_STATUS_OK; // OpenNI props if (strcmp(strName, XN_STREAM_PROPERTY_CROPPING) == 0) { nRetVal = m_pNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie, strModule, XN_PROP_CROPPING, sizeof(XnCropping), gbValue.pData); } else { nRetVal = m_pNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie, strModule, strName, gbValue.nDataSize, gbValue.pData); } XN_IS_STATUS_OK(nRetVal); return (XN_STATUS_OK); } XnStatus XnFileDevice::ReadStreamData() { XnStatus nRetVal = XN_STATUS_OK; XnCompressionFormats nCompression; XnUInt32 nCompressedSize; nRetVal = m_pDataPacker->ReadStreamDataProps(m_pStreamData, &nCompression, &nCompressedSize); XN_IS_STATUS_OK(nRetVal); nRetVal = HandleStreamData(m_pStreamData, nCompression, nCompressedSize); XN_IS_STATUS_OK(nRetVal); return (XN_STATUS_OK); } void TransformRGB24ToGrayscale16(XnUInt8* pBuffer, XnUInt32* pnBufferSize) { XnRGB24Pixel* pInput = (XnRGB24Pixel*)pBuffer; XnRGB24Pixel* pBufferEnd = (XnRGB24Pixel*)(pBuffer + *pnBufferSize); XnUInt16* pOutput = (XnUInt16*)pBuffer; while (pInput < pBufferEnd) { *pOutput = ((XnUInt16)pInput->nRed) << 2; pInput++; pOutput++; } *pnBufferSize = (XnUInt32)((XnUInt8*)pOutput - pBuffer); } XnStatus XnFileDevice::HandleStreamData(XnStreamData* pDataProps, XnCompressionFormats /*nCompression*/, XnUInt32 /*nCompressedSize*/) { XnStatus nRetVal = XN_STATUS_OK; XnUInt32 nPosition; nRetVal = m_pInputStream->Tell(&nPosition); XN_IS_STATUS_OK(nRetVal); XnUIntHash::Iterator it = m_PositionsToIgnore.End(); if (XN_STATUS_OK == m_PositionsToIgnore.Find(nPosition, it)) { // ignore this one. Just update the frame ID XnNodeInfo* pNodeInfo = NULL; nRetVal = m_nodeInfoMap.Get(pDataProps->StreamName, pNodeInfo); XN_IS_STATUS_OK(nRetVal); pNodeInfo->nCurrFrameID++; // and remove it from list nRetVal = m_PositionsToIgnore.Remove(it); XN_IS_STATUS_OK(nRetVal); } else { // take the codec XnNodeInfo* pNodeInfo; nRetVal = m_nodeInfoMap.Get(pDataProps->StreamName, pNodeInfo); XN_IS_STATUS_OK(nRetVal); // now uncompress data nRetVal = m_pDataPacker->ReadStreamData(pDataProps, pNodeInfo->pXnCodec); XN_IS_STATUS_OK(nRetVal); if (!m_bHighresTimestamps) { pDataProps->nTimestamp *= 1000; } if (pNodeInfo->bIRisRGB) { // covert RGB IR to regular IR TransformRGB24ToGrayscale16((XnUInt8*)pDataProps->pData, &pDataProps->nDataSize); } // update curr timestamp if (pDataProps->nTimestamp > m_nCurrTimestamp) { m_nCurrTimestamp = pDataProps->nTimestamp; } // update frame ID ++pNodeInfo->nCurrFrameID; // and notify about new data nRetVal = m_pNotifications->OnNodeNewData(m_pNotificationsCookie, pDataProps->StreamName, pDataProps->nTimestamp, pNodeInfo->nCurrFrameID, pDataProps->pData, pDataProps->nDataSize); XN_IS_STATUS_OK(nRetVal); } return (XN_STATUS_OK); } XnStatus XnFileDevice::HandleEndOfStream() { XnStatus nRetVal = XN_STATUS_OK; if (!m_bFileHasData) { XN_LOG_WARNING_RETURN(XN_STATUS_CORRUPT_FILE, XN_MASK_FILE, "File does not contain any data..."); } nRetVal = m_eofEvent.Raise(); XN_IS_STATUS_OK(nRetVal); if (m_bRepeat) { nRetVal = Rewind(); XN_IS_STATUS_OK(nRetVal); } else { m_bEOF = TRUE; } return (XN_STATUS_OK); } XnStatus XnFileDevice::ReadNextEventFromStream(XnPackedDataType* pnObjectType /* = NULL */) { XnStatus nRetVal = XN_STATUS_OK; XnPackedDataType nObjectType; nRetVal = m_pDataPacker->ReadNextObject(&nObjectType); XN_IS_STATUS_OK(nRetVal); nRetVal = HandlePackedObject(nObjectType); XN_IS_STATUS_OK(nRetVal); if (pnObjectType != NULL) { *pnObjectType = nObjectType; } return (XN_STATUS_OK); } XnStatus XnFileDevice::ReadTillNextData(XnBool* pbWrapOccurred) { XnStatus nRetVal = XN_STATUS_OK; *pbWrapOccurred = FALSE; if (m_nFileVersion < 4) { nRetVal = BCReadFrame(pbWrapOccurred); XN_IS_STATUS_OK(nRetVal); } else { XnPackedDataType nType = XN_PACKED_END; while ((nType != XN_PACKED_STREAM_DATA) && (!m_bEOF)) { nRetVal = ReadNextEventFromStream(&nType); XN_IS_STATUS_OK(nRetVal); if (nType == XN_PACKED_END) { *pbWrapOccurred = TRUE; } } if (nType == XN_PACKED_STREAM_DATA) { m_bFileHasData = TRUE; } } return (XN_STATUS_OK); } XnStatus XnFileDevice::Rewind() { XnStatus nRetVal = XN_STATUS_OK; // go back to start of stream nRetVal = m_pInputStream->Seek(XN_DEVICE_FILE_MAGIC_LEN); XN_IS_STATUS_OK(nRetVal); // read initial state XN_PROPERTY_SET_CREATE_ON_STACK(state); nRetVal = ReadInitialState(&state); XN_IS_STATUS_OK(nRetVal); // first handle current streams. remove or reset them for (XnNodeInfoMap::Iterator it = m_nodeInfoMap.Begin(); it != m_nodeInfoMap.End(); ++it) { const XnChar* strName = it->Key(); if (m_bNodeCollectionChanged) { // we need to destroy all streams, and recreate them later nRetVal = m_pNotifications->OnNodeRemoved(m_pNotificationsCookie, strName); XN_IS_STATUS_OK(nRetVal); } else { // just reset frame ID it->Value().nCurrFrameID = 0; // and mark not to recreate it nRetVal = m_ignoreNewNodes.Set(strName, it->Value()); XN_IS_STATUS_OK(nRetVal); } } // if we need, recreate nodes if (m_bNodeCollectionChanged) { nRetVal = SetInitialState(&state); XN_IS_STATUS_OK(nRetVal); } // ResetLastTimestampAndFrame(); // m_nReferenceTimestamp = 0; // m_nReferenceTime = 0; m_bNodeCollectionChanged = FALSE; m_nCurrTimestamp = 0; return (XN_STATUS_OK); } XnStatus XnFileDevice::UpdateS2DTables(const xn::DepthGenerator& depth) { XnStatus nRetVal = XN_STATUS_OK; XnUInt64 nTemp; XnDouble dTemp; // get config XnShiftToDepthConfig config; nRetVal = depth.GetIntProperty(XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE, nTemp); XN_IS_STATUS_OK(nRetVal); config.nZeroPlaneDistance = (XnDepthPixel)nTemp; nRetVal = depth.GetRealProperty(XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE, dTemp); XN_IS_STATUS_OK(nRetVal); config.fZeroPlanePixelSize = (XnFloat)dTemp; nRetVal = depth.GetRealProperty(XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE, dTemp); XN_IS_STATUS_OK(nRetVal); config.fEmitterDCmosDistance = (XnFloat)dTemp; nRetVal = depth.GetIntProperty(XN_STREAM_PROPERTY_MAX_SHIFT, nTemp); XN_IS_STATUS_OK(nRetVal); config.nDeviceMaxShiftValue = (XnUInt32)nTemp; config.nDeviceMaxDepthValue = depth.GetDeviceMaxDepth(); nRetVal = depth.GetIntProperty(XN_STREAM_PROPERTY_CONST_SHIFT, nTemp); XN_IS_STATUS_OK(nRetVal); config.nConstShift = (XnUInt32)nTemp; nRetVal = depth.GetIntProperty(XN_STREAM_PROPERTY_PIXEL_SIZE_FACTOR, nTemp); XN_IS_STATUS_OK(nRetVal); config.nPixelSizeFactor = (XnUInt32)nTemp; nRetVal = depth.GetIntProperty(XN_STREAM_PROPERTY_PARAM_COEFF, nTemp); XN_IS_STATUS_OK(nRetVal); config.nParamCoeff = (XnUInt32)nTemp; nRetVal = depth.GetIntProperty(XN_STREAM_PROPERTY_SHIFT_SCALE, nTemp); XN_IS_STATUS_OK(nRetVal); config.nShiftScale = (XnUInt32)nTemp; config.nDepthMinCutOff = 0; config.nDepthMaxCutOff = (XnDepthPixel)config.nDeviceMaxDepthValue; if (!m_ShiftToDepth.bIsInitialized) { nRetVal = XnShiftToDepthInit(&m_ShiftToDepth, &config); XN_IS_STATUS_OK(nRetVal); } else { nRetVal = XnShiftToDepthUpdate(&m_ShiftToDepth, &config); XN_IS_STATUS_OK(nRetVal); } // notify nRetVal = m_pNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie, depth.GetName(), XN_STREAM_PROPERTY_S2D_TABLE, m_ShiftToDepth.nShiftsCount * sizeof(XnDepthPixel), m_ShiftToDepth.pShiftToDepthTable); XN_IS_STATUS_OK(nRetVal); nRetVal = m_pNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie, depth.GetName(), XN_STREAM_PROPERTY_D2S_TABLE, m_ShiftToDepth.nDepthsCount * sizeof(XnUInt16), m_ShiftToDepth.pDepthToShiftTable); XN_IS_STATUS_OK(nRetVal); return (XN_STATUS_OK); } XnStatus XnFileDevice::UpdateRWData(const xn::DepthGenerator& depth) { XnStatus nRetVal = XN_STATUS_OK; XnUInt64 nZPD; nRetVal = depth.GetIntProperty(XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE, nZPD); XN_IS_STATUS_OK(nRetVal); XnDouble fZPPS; nRetVal = depth.GetRealProperty(XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE, fZPPS); XN_IS_STATUS_OK(nRetVal); XnFieldOfView FOV; FOV.fHFOV = 2*atan(fZPPS*XN_SXGA_X_RES/2/nZPD); FOV.fVFOV = 2*atan(fZPPS*XN_VGA_Y_RES*2/2/nZPD); // notify nRetVal = m_pNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie, depth.GetName(), XN_PROP_FIELD_OF_VIEW, sizeof(FOV), &FOV); XN_IS_STATUS_OK(nRetVal); return (XN_STATUS_OK); } XnNodeHandle XnFileDevice::GetSelfNodeHandle() { if (m_hSelf == NULL) { xn::Player player; XnStatus nRetVal = m_context.GetProductionNodeByName(m_strName, player); XN_ASSERT(nRetVal == XN_STATUS_OK); // keep only the handle (we don't want to keep a reference to ourself. This will prevent destruction) m_hSelf = player; } return m_hSelf; }