XnStatus XnSharedMemoryBufferPool::AllocateBuffers()
{
	XnStatus nRetVal = XN_STATUS_OK;
	
	if (m_nBufferSize > m_nMaxBufferSize)
	{
		return XN_STATUS_ALLOC_FAILED;
	}

	if (m_pSharedMemoryAddress != NULL)
	{
		// already allocated. nothing to do here
		return (XN_STATUS_OK);
	}

	// first time. allocate shared memory
	XnUInt32 nTotalSize = m_nMaxBufferSize * m_nBufferCount;
	nRetVal = xnOSCreateSharedMemory(m_strName, nTotalSize, XN_OS_FILE_READ | XN_OS_FILE_WRITE, &m_hSharedMemory);
	XN_IS_STATUS_OK(nRetVal);

	void* pAddress;
	nRetVal = xnOSSharedMemoryGetAddress(m_hSharedMemory, &pAddress);
	if (nRetVal != XN_STATUS_OK)
	{
		xnOSCloseSharedMemory(m_hSharedMemory);
		m_hSharedMemory = NULL;
		return (nRetVal);
	}

	m_pSharedMemoryAddress = (XnUChar*)pAddress;

	// now allocate buffers
	for (XnUInt32 i = 0; i < m_nBufferCount; ++i)
	{
		XnBufferInPool* pBuffer = XN_NEW(XnBufferInPool);
		if (pBuffer == NULL)
		{
			Free();
			return (XN_STATUS_ALLOC_FAILED);
		}

		pBuffer->m_nID = i;

		pBuffer->SetExternalBuffer(m_pSharedMemoryAddress + i*m_nMaxBufferSize, m_nMaxBufferSize);

		xnDumpWriteString(Dump(), "Allocated buffer %u with size %u\n", i, m_nMaxBufferSize);

		// add it to free list
		m_AllBuffers.AddLast(pBuffer);
		m_FreeBuffers.AddLast(pBuffer);
	}

	return (XN_STATUS_OK);
}
XnStatus XnSensorAudioStream::ReallocBuffer()
{
	XnStatus nRetVal = XN_STATUS_OK;

	XnDevicePrivateData* pDevicePrivateData = m_Helper.GetPrivateData();

	if (m_hSharedMemory == NULL)
	{
		// first time, create shared memory

		// we allocate enough for 5 seconds of audio
		XnUInt32 nSampleSize = 2 * 2; // 16-bit per channel (2 bytes) * max number of channels (2)
		XnUInt32 nSamples = 48000 * 5; // max sample rate * number of seconds

		XnUInt32 nMaxBufferSize = nSamples * nSampleSize;

		// find min packet size (so we'll have max packet count)
		XnUInt32 nMinPacketSize = XN_MIN(XN_SENSOR_PROTOCOL_AUDIO_PACKET_SIZE_BULK, XN_SENSOR_PROTOCOL_AUDIO_PACKET_SIZE_ISO);
		XnUInt32 nMaxPacketCount = nMaxBufferSize / nMinPacketSize - 1;

		XnUInt32 nSharedBufferSize = 
			sizeof(XnAudioSharedBuffer) + // header
			sizeof(XnUInt64) * nMaxPacketCount + // packet timestamps
			nMaxBufferSize;

		// to make the name unique, we'll add process ID
		XN_PROCESS_ID procID;
		xnOSGetCurrentProcessID(&procID);
		XnChar strSharedName[XN_DEVICE_MAX_STRING_LENGTH];
		sprintf(strSharedName, "%u_%s_%s", procID, m_strDeviceName, GetName());

		nRetVal = m_SharedBufferName.UnsafeUpdateValue(strSharedName);
		XN_IS_STATUS_OK(nRetVal);

		nRetVal = RequiredSizeProperty().UnsafeUpdateValue(nMaxBufferSize);
		XN_IS_STATUS_OK(nRetVal);

		nRetVal = xnOSCreateSharedMemory(strSharedName, nSharedBufferSize, XN_OS_FILE_READ | XN_OS_FILE_WRITE, &m_hSharedMemory);
		XN_IS_STATUS_OK(nRetVal);

		XnUChar* pAddress;
		nRetVal = xnOSSharedMemoryGetAddress(m_hSharedMemory, (void**)&pAddress);
		XN_IS_STATUS_OK(nRetVal);

		m_pSharedHeader = (XnAudioSharedBuffer*)pAddress;
		pDevicePrivateData->pAudioPacketsTimestamps = (XnUInt64*)(pAddress + sizeof(XnAudioSharedBuffer));
		pDevicePrivateData->pAudioBuffer = (XN_AUDIO_TYPE*)(pAddress + sizeof(XnAudioSharedBuffer) + sizeof(XnUInt64) * nMaxPacketCount);
		pDevicePrivateData->nAudioBufferSize = nMaxBufferSize;

		m_pSharedHeader->nTimestampsListOffset = sizeof(XnAudioSharedBuffer);
		m_pSharedHeader->nBufferOffset = pDevicePrivateData->pAudioBuffer - pAddress;
	}

	// calculate current packet size
	pDevicePrivateData->nAudioPacketSize = m_nOrigAudioPacketSize;

	if (m_Helper.GetFirmwareVersion() >= XN_SENSOR_FW_VER_5_2 && GetNumberOfChannels() == 1)
	{
		pDevicePrivateData->nAudioPacketSize /= 2;
	}

	pDevicePrivateData->nAudioBufferNumOfPackets = pDevicePrivateData->nAudioBufferSize / pDevicePrivateData->nAudioPacketSize;
	pDevicePrivateData->nAudioBufferSize = pDevicePrivateData->nAudioBufferNumOfPackets * pDevicePrivateData->nAudioPacketSize;

	m_pSharedHeader->nPacketCount = pDevicePrivateData->nAudioBufferNumOfPackets;
	m_pSharedHeader->nPacketSize = pDevicePrivateData->nAudioPacketSize;

	// set read and write indices
	pDevicePrivateData->nAudioReadIndex = 0;
	pDevicePrivateData->nAudioWriteIndex = 0;

	return (XN_STATUS_OK);
}
XnStatus XnServerSensorInvoker::SetStreamSharedMemory(SensorInvokerStream* pStream)
{
	XnStatus nRetVal = XN_STATUS_OK;
	
	// give shared memory a name (to make the name unique, we'll add process ID)
	XN_PROCESS_ID procID;
	xnOSGetCurrentProcessID(&procID);
	XnChar strSharedMemoryName[XN_FILE_MAX_PATH];
	sprintf(strSharedMemoryName, "%u_%s_%s", (XnUInt32)procID, m_sensor.GetUSBPath(), pStream->strType);
	nRetVal = pStream->pSharedMemoryName->UnsafeUpdateValue(strSharedMemoryName);
	XN_IS_STATUS_OK(nRetVal);

	XnUInt32 nBufferSize = 0;
	XnUInt32 nPixelSize = 0;

	if (strcmp(pStream->strType, XN_STREAM_TYPE_DEPTH) == 0)
	{
		// have space for depth and shift values
		nPixelSize = sizeof(XnDepthPixel) + sizeof(XnUInt16);
	}
	else if (strcmp(pStream->strType, XN_STREAM_TYPE_IMAGE) == 0)
	{
		// biggest pixel size is the RGB24
		nPixelSize = sizeof(XnRGB24Pixel);
	}
	else if (strcmp(pStream->strType, XN_STREAM_TYPE_IR) == 0)
	{
		// biggest pixel size is the RGB24
		nPixelSize = sizeof(XnIRPixel);
	}
	else
	{
		XN_ASSERT(FALSE);
		return XN_STATUS_ERROR;
	}

	// find out max resolution
	XnUInt32 nMaxNumPixels = 0;
	nRetVal = GetStreamMaxResolution(pStream, nMaxNumPixels);
	XN_IS_STATUS_OK(nRetVal);

	nBufferSize = (XnUInt32)(nMaxNumPixels * nPixelSize * m_numberOfBuffers.GetValue());

	// allocate shared memory
	nRetVal = xnOSCreateSharedMemoryEx(strSharedMemoryName, nBufferSize, XN_OS_FILE_READ | XN_OS_FILE_WRITE, m_allowOtherUsers.GetValue() == TRUE, &pStream->hSharedMemory);
	XN_IS_STATUS_OK(nRetVal);

	nRetVal = xnOSSharedMemoryGetAddress(pStream->hSharedMemory, (void**)&pStream->pSharedMemoryAddress);
	XN_IS_STATUS_OK(nRetVal);

	// Set buffer pool for this stream
	XnGeneralBuffer* aBuffers = XN_NEW_ARR(XnGeneralBuffer, m_numberOfBuffers.GetValue());
	XnUInt32 nSingleBufferSize = nBufferSize / m_numberOfBuffers.GetValue();
	for (XnUInt32 i = 0; i < m_numberOfBuffers.GetValue(); ++i)
	{
		aBuffers[i].pData = pStream->pSharedMemoryAddress + (i * nSingleBufferSize);
		aBuffers[i].nDataSize = nSingleBufferSize;
	}

	nRetVal = m_sensor.SetProperty(pStream->strType, XN_STREAM_PROPERTY_EXTERNAL_BUFFER_POOL, XnGeneralBufferPack(aBuffers, m_numberOfBuffers.GetValue() * sizeof(XnGeneralBuffer)));
	XN_DELETE_ARR(aBuffers);

	XN_IS_STATUS_OK(nRetVal);
	
	return (XN_STATUS_OK);
}