コード例 #1
0
ファイル: PlayerNode.cpp プロジェクト: 3david/OpenNI
XnStatus PlayerNode::UndoRecord(PlayerNode::RecordUndoInfo& undoInfo, XnUInt32 nDestPos, XnBool& bUndone)
{
	XnStatus nRetVal = XN_STATUS_OK;
	XnUInt32 nOriginalPos = TellStream();
	bUndone = FALSE;
	Record record(m_pRecordBuffer, RECORD_MAX_SIZE);
	while ((undoInfo.nRecordPos > nDestPos) && (undoInfo.nUndoRecordPos != 0))
	{
		nRetVal = SeekStream(XN_OS_SEEK_SET, undoInfo.nUndoRecordPos);
		XN_IS_STATUS_OK(nRetVal);
		nRetVal = ReadRecordHeader(record);
		XN_IS_STATUS_OK(nRetVal);
		undoInfo.nRecordPos = undoInfo.nUndoRecordPos;
		undoInfo.nUndoRecordPos = record.GetUndoRecordPos();
	}

	if (undoInfo.nRecordPos <= nDestPos)
	{
		/*We found a record that can undo the record originally pointed to by undoInfo.nDestRecordPos, 
		  so now we handle it. */
		nRetVal = ReadRecordFields(record);
		XN_IS_STATUS_OK(nRetVal);
		nRetVal = HandleRecord(record, FALSE);
		XN_IS_STATUS_OK(nRetVal);
		bUndone = TRUE;
	}
	else
	{
		nRetVal = SeekStream(XN_OS_SEEK_SET, nOriginalPos);
		XN_IS_STATUS_OK(nRetVal);
	}
	return XN_STATUS_OK;
}
コード例 #2
0
ファイル: PlayerNode.cpp プロジェクト: 3david/OpenNI
XnStatus PlayerNode::HandleStringPropRecord(StringPropRecord record)
{
	XN_VALIDATE_INPUT_PTR(m_pNodeNotifications);
	XnStatus nRetVal = record.Decode();
	XN_IS_STATUS_OK(nRetVal);
	DEBUG_LOG_RECORD(record, "StringProp");
	PlayerNodeInfo* pPlayerNodeInfo = GetPlayerNodeInfo(record.GetNodeID());
	XN_VALIDATE_PTR(pPlayerNodeInfo, XN_STATUS_CORRUPT_FILE);
	if (!pPlayerNodeInfo->bValid)
	{
		XN_ASSERT(FALSE);
		return XN_STATUS_CORRUPT_FILE;
	}

	nRetVal = m_pNodeNotifications->OnNodeStringPropChanged(m_pNotificationsCookie, 
		pPlayerNodeInfo->strName,
		record.GetPropName(),
		record.GetValue());
	XN_IS_STATUS_OK(nRetVal);

	nRetVal = SaveRecordUndoInfo(pPlayerNodeInfo, 
		record.GetPropName(), 
		TellStream() - record.GetSize(),
		record.GetUndoRecordPos());
	XN_IS_STATUS_OK(nRetVal);

	return XN_STATUS_OK;
}
コード例 #3
0
ファイル: PlayerNode.cpp プロジェクト: 3david/OpenNI
XnStatus PlayerNode::SeekToRecordByType(XnUInt32 nNodeID, RecordType type)
{
	XnStatus nRetVal = XN_STATUS_OK;
	
	Record record(m_pRecordBuffer, RECORD_MAX_SIZE);

	XnUInt32 nStartPos = TellStream();

	XnBool bFound = FALSE;
	XnUInt32 nPosBeforeRecord = 0;
	while (!bFound && nRetVal == XN_STATUS_OK)
	{
		nPosBeforeRecord = TellStream();

		nRetVal = ReadRecord(record);
		XN_IS_STATUS_OK(nRetVal);

		if ((record.GetType() == type) && (record.GetNodeID() == nNodeID))
		{
			bFound = TRUE;
		}
		else if (record.GetType() == RECORD_END)
		{
			nRetVal = XN_STATUS_NO_MATCH;
		}
		else
		{
			// if record has payload, skip it
			nRetVal = SkipRecordPayload(record);
		}
	}

	if (bFound)
	{
		// seek to before requested record
		nRetVal = SeekStream(XN_OS_SEEK_SET, nPosBeforeRecord);
		XN_IS_STATUS_OK(nRetVal);
	}
	else
	{
		// seek back to starting position
		SeekStream(XN_OS_SEEK_SET, nStartPos);
		return (nRetVal);
	}
	
	return (XN_STATUS_OK);
}
コード例 #4
0
ファイル: PlayerNode.cpp プロジェクト: jgollub/MetaImagerProj
XnStatus PlayerNode::HandleNodeAddedRecord(NodeAddedRecord record)
{
	XnStatus nRetVal = XN_STATUS_OK;

	nRetVal = record.Decode();
	XN_IS_STATUS_OK(nRetVal);

	DEBUG_LOG_RECORD(record, "NodeAdded");

	nRetVal = HandleNodeAddedImpl(
		record.GetNodeID(), record.GetNodeType(), record.GetNodeName(), record.GetCompression(),
		record.GetNumberOfFrames(), record.GetMinTimestamp(), record.GetMaxTimestamp());
	XN_IS_STATUS_OK(nRetVal);

	// get seek table (if exists)
	if (record.GetNumberOfFrames() > 0 && record.GetSeekTablePosition() != 0)
	{
		XnUInt32 nCurrPos = TellStream();

		nRetVal = SeekStream(XN_OS_SEEK_SET, record.GetSeekTablePosition());
		XN_IS_STATUS_OK(nRetVal);

		DataIndexRecordHeader seekTableHeader(m_pRecordBuffer, RECORD_MAX_SIZE);
		nRetVal = ReadRecord(seekTableHeader);
		XN_IS_STATUS_OK(nRetVal);

		nRetVal = HandleDataIndexRecord(seekTableHeader, TRUE);
		XN_IS_STATUS_OK(nRetVal);

		// and seek back
		nRetVal = SeekStream(XN_OS_SEEK_SET, nCurrPos);
		XN_IS_STATUS_OK(nRetVal);
	}

	return (XN_STATUS_OK);
}
コード例 #5
0
ファイル: PlayerNode.cpp プロジェクト: 3david/OpenNI
XnStatus PlayerNode::HandleGeneralPropRecord(GeneralPropRecord record)
{
	XN_VALIDATE_INPUT_PTR(m_pNodeNotifications);
	XnStatus nRetVal = record.Decode();
	XN_IS_STATUS_OK(nRetVal);
	DEBUG_LOG_RECORD(record, "GeneralProp");

	PlayerNodeInfo* pPlayerNodeInfo = GetPlayerNodeInfo(record.GetNodeID());
	XN_VALIDATE_PTR(pPlayerNodeInfo, XN_STATUS_CORRUPT_FILE);
	if (!pPlayerNodeInfo->bValid)
	{
		XN_ASSERT(FALSE);
		return XN_STATUS_CORRUPT_FILE;
	}

	// Fix backwards compatibility issues
	if (strcmp(record.GetPropName(), XN_PROP_REAL_WORLD_TRANSLATION_DATA) == 0)
	{
		// old recordings held the RealWorldTranslationData, but API has changed. Translate
		// it to Field Of View
		if (record.GetPropDataSize() != sizeof(XnRealWorldTranslationData))
		{
			return XN_STATUS_CORRUPT_FILE;
		}

		const XnRealWorldTranslationData* pTransData = (const XnRealWorldTranslationData*)record.GetPropData();

		// we also need resolution for the translation
		xn::DepthGenerator depthGen;
		nRetVal = m_context.GetProductionNodeByName(pPlayerNodeInfo->strName, depthGen);
		XN_IS_STATUS_OK(nRetVal);

		XnMapOutputMode outputMode;
		nRetVal = depthGen.GetMapOutputMode(outputMode);
		XN_IS_STATUS_OK(nRetVal);
		
		XnFieldOfView FOV;
		FOV.fHFOV = 2*atan(pTransData->dPixelSizeAtZeroPlane * pTransData->dSourceToDepthPixelRatio * outputMode.nXRes / 2 / pTransData->dZeroPlaneDistance);
		FOV.fVFOV = 2*atan(pTransData->dPixelSizeAtZeroPlane * pTransData->dSourceToDepthPixelRatio * outputMode.nYRes / 2 / pTransData->dZeroPlaneDistance);

		nRetVal = m_pNodeNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie,
			pPlayerNodeInfo->strName,
			XN_PROP_FIELD_OF_VIEW,
			sizeof(FOV),
			&FOV);
		XN_IS_STATUS_OK(nRetVal);
	}
	else
	{
		nRetVal = m_pNodeNotifications->OnNodeGeneralPropChanged(m_pNotificationsCookie,
			pPlayerNodeInfo->strName, 
			record.GetPropName(),
			record.GetPropDataSize(),
			record.GetPropData());
		XN_IS_STATUS_OK(nRetVal);
	}
	
	nRetVal = SaveRecordUndoInfo(pPlayerNodeInfo, 
		record.GetPropName(), 
		TellStream() - record.GetSize(),
		record.GetUndoRecordPos());
	XN_IS_STATUS_OK(nRetVal);

	return XN_STATUS_OK;
}
コード例 #6
0
ファイル: PlayerNode.cpp プロジェクト: 3david/OpenNI
XnStatus PlayerNode::HandleNodeAdded_1_0_0_4_Record(NodeAdded_1_0_0_4_Record record)
{
	XnStatus nRetVal = XN_STATUS_OK;

	nRetVal = record.Decode();
	XN_IS_STATUS_OK(nRetVal);

	DEBUG_LOG_RECORD(record, "NodeAdded1_0_0_4");

	/** BC issue **/
	// NOTE: ONI files up to version 1.0.0.4 didn't had a different NodeAdded record. It did
	// not contain seek data (number of frames and min/max timestamp). Instead, this data was
	// in the DataBegin record. So we need to also find this record, and read these props from it.

	XnUInt32 nNodeID = record.GetNodeID();
	XnChar strName[XN_MAX_NAME_LENGTH];
	nRetVal = xnOSStrCopy(strName, record.GetNodeName(), XN_MAX_NAME_LENGTH);
	XN_IS_STATUS_OK(nRetVal);
	XnProductionNodeType type = record.GetNodeType();
	XnCodecID compression = record.GetCompression();
	XnUInt32 nNumFrames = 0;
	XnUInt64 nMinTimestamp = 0;
	XnUInt64 nMaxTimestamp = 0;

	if (xnIsTypeGenerator(type))
	{
		// we need to look for the DataBegin record to have number of frames, etc.
		XnUInt32 nStartPos = TellStream();

		// NOTE: this overwrites the current NodeAdded record buffer!!!
		nRetVal = SeekToRecordByType(nNodeID, RECORD_NODE_DATA_BEGIN);
		if (nRetVal == XN_STATUS_OK)
		{
			NodeDataBeginRecord dataBeginRecord(m_pRecordBuffer, RECORD_MAX_SIZE);
			nRetVal = ReadRecord(dataBeginRecord);
			XN_IS_STATUS_OK(nRetVal);

			nRetVal = dataBeginRecord.Decode();
			XN_IS_STATUS_OK(nRetVal);

			nNumFrames = dataBeginRecord.GetNumFrames();
			nMaxTimestamp = dataBeginRecord.GetMaxTimeStamp();

			// also find data record for min timestamp
			nRetVal = SeekToRecordByType(record.GetNodeID(), RECORD_NEW_DATA);
			if (nRetVal == XN_STATUS_OK)
			{
				NewDataRecordHeader newDataRecord(m_pRecordBuffer, RECORD_MAX_SIZE);
				nRetVal = ReadRecord(newDataRecord);
				XN_IS_STATUS_OK(nRetVal);

				nRetVal = newDataRecord.Decode();
				XN_IS_STATUS_OK(nRetVal);

				nMinTimestamp = newDataRecord.GetTimeStamp();
			}

			// get back to start position
			nRetVal = SeekStream(XN_OS_SEEK_SET, nStartPos);
			XN_IS_STATUS_OK(nRetVal);
		}
	}

	nRetVal = HandleNodeAddedImpl(nNodeID, type, strName, compression, nNumFrames, nMinTimestamp, nMaxTimestamp);
	XN_IS_STATUS_OK(nRetVal);

	return XN_STATUS_OK;
}
コード例 #7
0
ファイル: PlayerNode.cpp プロジェクト: 3david/OpenNI
XnStatus PlayerNode::SeekToFrameAbsolute(XnUInt32 nNodeID, XnUInt32 nDestFrame)
{
	XN_ASSERT((nNodeID != INVALID_NODE_ID) && (nNodeID < m_nMaxNodes));
	PlayerNodeInfo* pPlayerNodeInfo = &m_pNodeInfoMap[nNodeID];
	XN_ASSERT((nDestFrame > 0) && (nDestFrame <= pPlayerNodeInfo->nFrames));
	XN_VALIDATE_INPUT_PTR(m_pNodeNotifications);

	XnUInt32 nStartPos = TellStream();
	XnUInt32 nNextFrame = pPlayerNodeInfo->nCurFrame + 1;
	XnUInt32 nFrames = pPlayerNodeInfo->nFrames;
	XnStatus nRetVal = XN_STATUS_OK;

	if (nDestFrame == pPlayerNodeInfo->nCurFrame)
	{
		//Just go back to position of current frame
		nRetVal = SeekStream(XN_OS_SEEK_SET, pPlayerNodeInfo->nLastDataPos);
		XN_IS_STATUS_OK(nRetVal);
	}
	else if (nDestFrame < nNextFrame)
	{
		//Seek backwards
		XnUInt32 nDestRecordPos = pPlayerNodeInfo->newDataUndoInfo.nRecordPos;
		XnUInt32 nUndoRecordPos = pPlayerNodeInfo->newDataUndoInfo.nUndoRecordPos;
		NewDataRecordHeader record(m_pRecordBuffer, RECORD_MAX_SIZE);
		
		/*Scan back through the frames' undo positions until we get to a frame number that is smaller or equal
		  to nDestFrame. We put the position of the frame we find in nDestRecordPos. */
		do
		{
			if (nUndoRecordPos == 0)
			{
				/* The last frame we encountered doesn't have an undo frame. But this data frame can't be the first,
				   so the file is corrupt */
				XN_LOG_ERROR_RETURN(XN_STATUS_CORRUPT_FILE, XN_MASK_OPEN_NI, "Undo frame not found for frame in position %u", nDestRecordPos);
			}
			nRetVal = SeekStream(XN_OS_SEEK_SET, nUndoRecordPos);
			XN_IS_STATUS_OK(nRetVal);
			nDestRecordPos = nUndoRecordPos;
			record.ResetRead();
			nRetVal = ReadRecordHeader(record);
			XN_IS_STATUS_OK(nRetVal);
			if (record.GetType() != RECORD_NEW_DATA)
			{
				XN_ASSERT(FALSE);
				XN_LOG_ERROR_RETURN(XN_STATUS_CORRUPT_FILE, XN_MASK_OPEN_NI, "Unexpected record type: %u", record.GetType());
			}

			if (record.GetNodeID() != nNodeID)
			{
				XN_ASSERT(FALSE);
				XN_LOG_ERROR_RETURN(XN_STATUS_CORRUPT_FILE, XN_MASK_OPEN_NI, "Unexpected node id: %u", record.GetNodeID());
			}

			nRetVal = ReadRecordFields(record);
			XN_IS_STATUS_OK(nRetVal);
			nRetVal = record.Decode();
			XN_IS_STATUS_OK(nRetVal);
			nUndoRecordPos = record.GetUndoRecordPos();
		} while (record.GetFrameNumber() > nDestFrame);

		//Now handle the frame
		nRetVal = HandleNewDataRecord(record, FALSE);
		XnBool bUndone = FALSE;

		for (XnUInt32 i = 0; i < m_nMaxNodes; i++)
		{
			//Rollback all properties to match the state the stream was in at position nDestRecordPos
			PlayerNodeInfo &pni = m_pNodeInfoMap[i];
			for (RecordUndoInfoMap::Iterator it = pni.recordUndoInfoMap.begin(); 
				 it != pni.recordUndoInfoMap.end(); it++)
			{
				if ((it.Value().nRecordPos > nDestRecordPos) && (it.Value().nRecordPos < nStartPos))
				{
					//This property was set between nDestRecordPos and our start position, so we need to undo it.
					nRetVal = UndoRecord(it.Value(), nDestRecordPos, bUndone);
					XN_IS_STATUS_OK(nRetVal);
				}
			}

			if ((i != nNodeID) && pni.bIsGenerator)
			{
				//Undo all other generator nodes' data
				RecordUndoInfo &undoInfo = pni.newDataUndoInfo;
				if ((undoInfo.nRecordPos > nDestRecordPos) && (undoInfo.nRecordPos < nStartPos))
				{
					nRetVal = UndoRecord(undoInfo, nDestRecordPos, bUndone);
					XN_IS_STATUS_OK(nRetVal);
					if (!bUndone)
					{
						//We couldn't find a record that can undo this data record
						pni.nLastDataPos = 0;
						pni.newDataUndoInfo.Reset();
					}
				}
			}
		}

		/*Now, for each node, go to the position of the last encountered data record, and process that record
		  (including its payload).*/
		/*TODO: Optimization: remember each node's last data pos, and later, see if it changes. Only process data
		  frames of nodes whose last data pos actually changed.*/

		nRetVal = ProcessEachNodeLastData(nNodeID);
		XN_IS_STATUS_OK(nRetVal);
	}
	else //(nDestFrame >= nNextFrame)
	{
		//Skip all frames until we get to our frame number, but handle any properties we run into.
		while (pPlayerNodeInfo->nCurFrame < nDestFrame)
		{
			nRetVal = ProcessRecord(FALSE);
			XN_IS_STATUS_OK(nRetVal);
		}

		/*Now, for each node, go to the position of the last encountered data record, and process that record
		  (including its payload).*/
		/*TODO: Optimization: remember each node's last data pos, and later, see if it changes. Only process data
		  frames of nodes whose last data pos actually changed.*/
		nRetVal = ProcessEachNodeLastData(nNodeID);
		XN_IS_STATUS_OK(nRetVal);
	}

	return XN_STATUS_OK;
}
コード例 #8
0
ファイル: PlayerNode.cpp プロジェクト: 3david/OpenNI
XnStatus PlayerNode::SeekToTimeStampAbsolute(XnUInt64 nDestTimeStamp)
{
	XnStatus nRetVal = XN_STATUS_OK;
	XnUInt64 nRecordTimeStamp = 0LL;
	XnUInt32 nStartPos = TellStream(); //We'll revert to this in case nDestTimeStamp is beyond end of stream
	XN_IS_STATUS_OK(nRetVal);

	if (nDestTimeStamp < m_nTimeStamp)
	{
		nRetVal = Rewind();
	}
	else if (nDestTimeStamp == m_nTimeStamp)
	{
		//Nothing to do
		return XN_STATUS_OK;
	}
	else if (nDestTimeStamp > m_nGlobalMaxTimeStamp)
	{
		nDestTimeStamp = m_nGlobalMaxTimeStamp;
	}

	Record record(m_pRecordBuffer, RECORD_MAX_SIZE);
	XnBool bEnd = FALSE;
	XnUInt32 nBytesRead = 0;

	while ((nRecordTimeStamp < nDestTimeStamp) && !bEnd)
	{
		nRetVal = ReadRecordHeader(record);
		XN_IS_STATUS_OK(nRetVal);
		switch (record.GetType())
		{
			case RECORD_NEW_DATA:
			{
				//We already read Record::HEADER_SIZE, now read the rest of the new data record header
				nRetVal = Read(m_pRecordBuffer + Record::HEADER_SIZE, 
					NewDataRecordHeader::MAX_SIZE - Record::HEADER_SIZE, 
					nBytesRead);
				XN_IS_STATUS_OK(nRetVal);
				if (nBytesRead < NewDataRecordHeader::MAX_SIZE - Record::HEADER_SIZE)
				{
					return XN_STATUS_CORRUPT_FILE;
				}
				NewDataRecordHeader newDataRecordHeader(record);
				nRetVal = newDataRecordHeader.Decode();
				XN_IS_STATUS_OK(nRetVal);
				//Save record time stamp
				nRecordTimeStamp = newDataRecordHeader.GetTimeStamp();
				
				if (nRecordTimeStamp >= nDestTimeStamp)
				{
					//We're done - move back to beginning of record
					nRetVal = SeekStream(XN_OS_SEEK_CUR, -XnInt32(nBytesRead));
					XN_IS_STATUS_OK(nRetVal);
				}
				else
				{
					//Skip to next record
					nRetVal = SeekStream(XN_OS_SEEK_CUR, 
						newDataRecordHeader.GetSize() - NewDataRecordHeader::MAX_SIZE);
					XN_IS_STATUS_OK(nRetVal);
				}
				break;
			}

			case RECORD_END:
			{
				bEnd = TRUE;
				break;
			}

			case RECORD_NODE_ADDED_1_0_0_4:
			case RECORD_NODE_ADDED:
			case RECORD_INT_PROPERTY:	
			case RECORD_REAL_PROPERTY:	
			case RECORD_STRING_PROPERTY:
			case RECORD_GENERAL_PROPERTY:
			case RECORD_NODE_REMOVED:	
			case RECORD_NODE_DATA_BEGIN:
			case RECORD_NODE_STATE_READY:
			{
				//Read rest of record and handle it normally
				nRetVal = Read(m_pRecordBuffer + Record::HEADER_SIZE, record.GetSize() - Record::HEADER_SIZE, nBytesRead);
				XN_IS_STATUS_OK(nRetVal);
				Record record(m_pRecordBuffer, RECORD_MAX_SIZE);
				nRetVal = HandleRecord(record, TRUE);
				XN_IS_STATUS_OK(nRetVal);
				break;
			}
			default:
			{
				XN_ASSERT(FALSE);
				return XN_STATUS_CORRUPT_FILE;
			}

		} //switch
	} //while
	
	if (bEnd)
	{
		SeekStream(XN_OS_SEEK_SET, nStartPos);
		return XN_STATUS_ILLEGAL_POSITION;
	}

	return XN_STATUS_OK;
}//function
コード例 #9
0
ファイル: PlayerNode.cpp プロジェクト: 3david/OpenNI
XnStatus PlayerNode::HandleNewDataRecord(NewDataRecordHeader record, XnBool bReadPayload)
{
	XN_VALIDATE_INPUT_PTR(m_pNodeNotifications);
	XnStatus nRetVal = record.Decode();
	XN_IS_STATUS_OK(nRetVal);
	DEBUG_LOG_RECORD(record, "NewData");

	XN_ASSERT(record.GetNodeID() != INVALID_NODE_ID);
	PlayerNodeInfo* pPlayerNodeInfo = GetPlayerNodeInfo(record.GetNodeID());
	XN_VALIDATE_PTR(pPlayerNodeInfo, XN_STATUS_CORRUPT_FILE);
	if (!pPlayerNodeInfo->bValid)
	{
		XN_ASSERT(FALSE);
		return XN_STATUS_CORRUPT_FILE;
	}

	XnUInt32 nRecordTotalSize = record.GetSize() + record.GetPayloadSize();
	if (nRecordTotalSize > RECORD_MAX_SIZE)
	{
		XN_ASSERT(FALSE);
		XN_LOG_ERROR_RETURN(XN_STATUS_INTERNAL_BUFFER_TOO_SMALL, XN_MASK_OPEN_NI, "Record size %u is larger than player internal buffer", nRecordTotalSize);
	}
	
	pPlayerNodeInfo->nLastDataPos = TellStream() - record.GetSize();
	pPlayerNodeInfo->newDataUndoInfo.nRecordPos =  pPlayerNodeInfo->nLastDataPos;
	pPlayerNodeInfo->newDataUndoInfo.nUndoRecordPos = record.GetUndoRecordPos();
	if (record.GetFrameNumber() > pPlayerNodeInfo->nFrames)
	{
		XN_ASSERT(FALSE);
		return XN_STATUS_CORRUPT_FILE;
	}

	pPlayerNodeInfo->nCurFrame = record.GetFrameNumber();
	
	if (record.GetTimeStamp() > m_nGlobalMaxTimeStamp)	
	{
		XN_ASSERT(FALSE);
		XN_LOG_ERROR_RETURN(XN_STATUS_CORRUPT_FILE, XN_MASK_OPEN_NI, "Record timestamp for record in position %u is larger than reported max timestamp", pPlayerNodeInfo->nLastDataPos);
	}

	m_nTimeStamp = record.GetTimeStamp();

	if (bReadPayload)
	{
		//Now read the actual data
		XnUInt32 nBytesRead = 0;
		nRetVal = Read(record.GetPayload(), record.GetPayloadSize(), nBytesRead);
		XN_IS_STATUS_OK(nRetVal);
		if (nBytesRead < record.GetPayloadSize())
		{
			XN_LOG_ERROR_RETURN(XN_STATUS_CORRUPT_FILE, XN_MASK_OPEN_NI, "Not enough bytes read");
		}

		const XnUInt8* pCompressedData = record.GetPayload(); //The new (compressed) data is right at the end of the header
		XnUInt32 nCompressedDataSize = record.GetPayloadSize();
		const XnUInt8* pUncompressedData = NULL;
		XnUInt32 nUncompressedDataSize = 0;
		XnCodecID compression = pPlayerNodeInfo->codec.GetCodecID();
		if (compression == XN_CODEC_UNCOMPRESSED)
		{
			pUncompressedData = pCompressedData;
			nUncompressedDataSize = nCompressedDataSize;
		}
		else
		{
			//Decode data with codec
			nRetVal = pPlayerNodeInfo->codec.DecodeData(pCompressedData, nCompressedDataSize, 
				m_pUncompressedData, DATA_MAX_SIZE, &nUncompressedDataSize);
			XN_IS_STATUS_OK(nRetVal);
			pUncompressedData = m_pUncompressedData;
		}

		nRetVal = m_pNodeNotifications->OnNodeNewData(m_pNotificationsCookie, pPlayerNodeInfo->strName, 
			record.GetTimeStamp(), record.GetFrameNumber(), pUncompressedData, nUncompressedDataSize);
		XN_IS_STATUS_OK(nRetVal);
	}
	else
	{
		//Just skip the data
		nRetVal = SkipRecordPayload(record);
		XN_IS_STATUS_OK(nRetVal);
	}

	return XN_STATUS_OK;
}