Low framerate using GT1030 and ReceiveImage

Hi, I’m using Nvidia GT1030, but I need to receive Spout image to memory. This is the approximate code:

int width = m_rcv.GetSenderWidth();
int height = m_rcv.GetSenderHeight();

if (m_rcv.IsUpdated())
{
	SAFE_DELETE_ARRAY(m_pBuffer);
	return SPOUT_ERR_FAIL;
}

if (width <= 0 || height <= 0)
{
	m_rcv.ReceiveImage(0);
	return SPOUT_ERR_FAIL;
}

if (!m_pBuffer)
{
	m_bufferSize = width * height * 4;
	m_pBuffer = new byte[m_bufferSize];
}

if (!m_rcv.ReceiveImage(m_pBuffer))
	return SPOUT_ERR_FAIL;

double fps = m_rcv.GetSenderFps();
return SPOUT_ERR_OK;

The variable m_rcv is the SpoutReceiver. I’m getting about 40fps in the fps variable, but the real output is maybe 2 FPS (resolution about 2000x2000). Is there a way to have smooth animation using CPU? I need to use the RGB values in CPU, I can’t use just the DX/GL bitmap.

How are you measuring the fps?

Try this re-arranged version -

if (m_rcv.ReceiveImage(m_pBuffer)) {
	if (m_rcv.IsUpdated()) {
		SAFE_DELETE_ARRAY(m_pBuffer);
		m_bufferSize = m_rcv.GetSenderWidth() * m_rcv.GetSenderHeight()t * 4;
		m_pBuffer = new byte[m_bufferSize];
	}
	double fps = m_rcv.GetSenderFps();
	return SPOUT_ERR_OK;
}

Thank you for your reply. I’ve updated the code as you’ve recommended:

	if (m_rcv.ReceiveImage(m_pBuffer))
	{
		if (m_rcv.IsUpdated()) {
			SAFE_DELETE_ARRAY(m_pBuffer);
			int width = m_rcv.GetSenderWidth();
			int height = m_rcv.GetSenderHeight();
			m_bufferSize = width * height * 4;
			m_pBuffer = new byte[m_bufferSize];
		}
		double fps = m_rcv.GetSenderFps();
		return SPOUT_ERR_OK;
	}

	return SPOUT_ERR_FAIL;

I’ve made a screen capture, where you can see the source (on the right) and received image over Spout (small image on the left in MainWindow). You can see it’s about 2FPS:

I’ve measured the FPS also in my code (how many frames I’m receiving) - it’s showing about 4-6 fps.

Is there some easy to use example available for Spout using CPU bitmaps? So I avoid my code and test the recommended way? Because all examples I’ve found used OpenGL render directly to screen.

There must be a reason for your finding but I can’t reproduce it. There is a DirectX example for image sending. This does not require any framework, so it would be useful If you could build this solution to see if it has the same problem.

You’re right, the problem was in C# bitmap creation process. Now it’s running at 30FPS. Just to explain the issue, I was using C# Bitmap LockBits to access RGBA data directly and copy from incoming Spout buffer:

var btmpData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
				System.Drawing.Imaging.ImageLockMode.ReadOnly,
				System.Drawing.Imaging.PixelFormat.Format32bppArgb);

			byte* pBitmapSrc = (byte*)receivedData.ToPointer();
			int srcStride = 4 * bitmap.Width;
			byte* pBitmapDest = (byte*)btmpData.Scan0.ToPointer();
			int wb = bitmap.Width;
			int hb = bitmap.Height;
			for (int y = 0; y < bitmap.Height; y++)
			{
				byte* pLineSrc = pBitmapSrc + y * srcStride;
				byte* pLineDest = pBitmapDest + y * btmpData.Stride;

				for (int x = 0; x < bitmap.Width; x++)
				{
					pLineDest[0] = pLineSrc[2];
					pLineDest[1] = pLineSrc[1];
					pLineDest[2] = pLineSrc[0];
					pLineDest[3] = pLineSrc[3];
					pLineSrc += 4;
					pLineDest += 4;
				}
			}
			bitmap.UnlockBits(btmpData);

The problem is in bitmap.Width and bitmap.Height - those slow down the process a lot. When I used local variables (int wb = bitmap.Width) instead, all is working fast. Strange …

Thank you for your help!

That’s good news. There must be an overhead for bitmap.Width and bitmap.Height but you would not expect it. If the bitmap stride is the same as the source stride, could you just copy the data.

	memcpy((void*)btmpData.Scan0.ToPointer(),
		(void*)receivedData.ToPointer(),
		bitmap.Width*bitmap.Height*4);

Or for additional speed, you might try a SpoutCopy function that uses SSE if the width is 16 byte aligned.

	m_rcv.spoutcopy.CopyPixels((const unsigned char*)receivedData.ToPointer(),
		(unsigned char*)btmpData.Scan0.ToPointer(),
		bitmap.Width, bitmap.Height);

There are also “rgba2rgba” functions that use SSE and allow for source and destination pitch.

Unfortunately that’s not possible, since the color order is different (in C# Bitmap class). Anyway, thank you for your help, really appreciated!

Edit: I noticed, there’s rgba2bgra function, that might work. Thank you.

OK, I missed the reason for the copy.

If that is the only problem, you can receive directly to the Bitmap buffer and specify GL_BGRA for the format. I checked that this works with the OpenGL example.

Originally this was only an RGBA/RGB option, but since then there have been updates to formats. I will look into revising the documentation and example.

Hi, thank you for the help, it’s working like a charm now. I want to ask, we are developing software for pixel LED mapping for about 10 years now (www.ledstripstudio.com) and it’s widely used across the world. Is it possible to add also our icon and link to your website, so the people know, we support Spout?

Thank you again.

Yes of course. Please contact me using the email shown on the GitHub Page.