[Bf-blender-cvs] [e936abd] decklink: BGE VideoDeckLink: Implement memory locking in Linux.

Benoit Bolsee noreply at git.blender.org
Fri May 1 20:44:09 CEST 2015


Commit: e936abdb3f75c3390b77d039985b9e0f1d52aac2
Author: Benoit Bolsee
Date:   Fri May 1 20:31:02 2015 +0200
Branches: decklink
https://developer.blender.org/rBe936abdb3f75c3390b77d039985b9e0f1d52aac2

BGE VideoDeckLink: Implement memory locking in Linux.

Use mlock() to lock memory in case of pinned memory extension.
Use get/setrlimit to set limit so thqt locking will work.
However, only privilege process can increase the limit, so ignore error.

===================================================================

M	source/gameengine/VideoTexture/VideoDeckLink.cpp
M	source/gameengine/VideoTexture/VideoDeckLink.h

===================================================================

diff --git a/source/gameengine/VideoTexture/VideoDeckLink.cpp b/source/gameengine/VideoTexture/VideoDeckLink.cpp
index db81612..85ff8bd 100644
--- a/source/gameengine/VideoTexture/VideoDeckLink.cpp
+++ b/source/gameengine/VideoTexture/VideoDeckLink.cpp
@@ -36,6 +36,11 @@
 #endif
 #include <stdint.h>
 #include <string.h>
+#ifndef WIN32
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/mman.h>
+#endif
 
 #include "MEM_guardedalloc.h"
 #include "PIL_time.h"
@@ -276,11 +281,14 @@ private:
 class TextureTransferPMD : public TextureTransfer
 {
 public:
-	TextureTransferPMD(GLuint texId, TextureDesc *pDesc, void *address)
+    TextureTransferPMD(GLuint texId, TextureDesc *pDesc, void *address, u_int allocatedSize)
 	{
 		memcpy(&mDesc, pDesc, sizeof(mDesc));
 		mTexId = texId;
 		mBuffer = address;
+        mAllocatedSize = allocatedSize;
+
+        _PinBuffer(address, allocatedSize);
 
 		// as we cache transfer object, we will create one texture to hold the buffer
 		glGenBuffers(1, &mPinnedTextureBuffer);
@@ -292,7 +300,9 @@ public:
 	~TextureTransferPMD()
 	{
 		glDeleteBuffers(1, &mPinnedTextureBuffer);
-	}
+        if (mBuffer)
+            _UnpinBuffer(mBuffer, mAllocatedSize);
+    }
 
 	virtual void PerformTransfer()
 	{
@@ -300,6 +310,7 @@ public:
 		glBindTexture(GL_TEXTURE_2D, mTexId);
 		// NULL for last arg indicates use current GL_PIXEL_UNPACK_BUFFER target as texture data
 		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mDesc.width, mDesc.height, mDesc.format, mDesc.type, NULL);
+        // wait for the trasnfer to complete
 		GLsync fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
 		glClientWaitSync(fence, GL_SYNC_FLUSH_COMMANDS_BIT, 40 * 1000 * 1000);	// timeout in nanosec
 		glDeleteSync(fence);
@@ -312,7 +323,9 @@ private:
 	GLuint mTexId;
 	// buffer
 	void *mBuffer;
-	// characteristic of the image
+    // the allocated size
+    u_int mAllocatedSize;
+    // characteristic of the image
 	TextureDesc mDesc;
 };
 
@@ -320,9 +333,8 @@ bool TextureTransfer::_PinBuffer(void *address, u_int size)
 {
 #ifdef WIN32
 	return VirtualLock(address, size);
-#else
-	// Linux doesn't have the equivalent?
-	return true;
+#elif defined(_POSIX_MEMLOCK_RANGE)
+    return !mlock(address, size);
 #endif
 }
 
@@ -330,6 +342,8 @@ void TextureTransfer::_UnpinBuffer(void* address, u_int size)
 {
 #ifdef WIN32
 	VirtualUnlock(address, size);
+#elif defined(_POSIX_MEMLOCK_RANGE)
+    munlock(address, size);
 #endif
 }
 
@@ -366,8 +380,21 @@ bool PinnedMemoryAllocator::ReserveMemory(size_t size)
 		return false;
 	mReservedProcessMemory = size;
 	CloseHandle(hProcess);
+    return true;
+#else
+    struct rlimit rlim;
+    if (getrlimit(RLIMIT_MEMLOCK, &rlim) == 0)
+    {
+        if (rlim.rlim_cur < size)
+        {
+            if (rlim.rlim_max < size)
+                rlim.rlim_max = size;
+            rlim.rlim_cur = size;
+            return !setrlimit(RLIMIT_MEMLOCK, &rlim);
+        }
+    }
+    return false;
 #endif
-	return true;
 }
 
 PinnedMemoryAllocator::PinnedMemoryAllocator(unsigned cacheSize, size_t memSize) :
@@ -476,7 +503,7 @@ void PinnedMemoryAllocator::TransferBuffer(void* address, TextureDesc* texDesc,
 #endif
 		if (mHasAMDPinnedMemory)
 		{
-			pTransfer = new TextureTransferPMD(texId, texDesc, address);
+            pTransfer = new TextureTransferPMD(texId, texDesc, address, allocatedSize);
 		}
 		else
 		{
@@ -520,9 +547,9 @@ HRESULT STDMETHODCALLTYPE	PinnedMemoryAllocator::AllocateBuffer(dl_size_t buffer
 	{
 		// Allocate memory on a page boundary
 		// Note: aligned alloc exist in Blender but only for small alignment, use direct allocation then.
-		// Note: the DeckLink API tries to allocate up to 65 buffer in advance, we will limit this to 5
+        // Note: the DeckLink API tries to allocate up to 65 buffer in advance, we will limit this to 3
 		//       because we don't need any caching
-		if (mAllocatedSize.size() >= 5)
+        if (mAllocatedSize.size() >= mBufferCacheSize)
 			*allocatedBuffer = NULL;
 		else 
 		{
@@ -879,9 +906,9 @@ void VideoDeckLink::openCam (char *format, short camIdx)
 			THRWEXCP(VideoDeckLinkBadFormat, S_OK);
 	}
 	// custom allocator, 3 frame in cache should be enough
-	// make sure we allow up to 10 frame in memory for pinning
+    // make sure we allow up to 5 frame in memory for pinning
 	// note: some pixel format take more than 4 bytes but the difference is small (9/8 versus 1)
-    mpAllocator = new PinnedMemoryAllocator(3, mFrameWidth*mTextureDesc.height * 4 * 10);
+    mpAllocator = new PinnedMemoryAllocator(3, mFrameWidth*mTextureDesc.height * 4 * 4);
 
 	if (mDLInput->SetVideoInputFrameMemoryAllocator(mpAllocator) != S_OK)
 		THRWEXCP(DeckLinkInternalError, S_OK);
diff --git a/source/gameengine/VideoTexture/VideoDeckLink.h b/source/gameengine/VideoTexture/VideoDeckLink.h
index 9043d1c..1c65b48 100644
--- a/source/gameengine/VideoTexture/VideoDeckLink.h
+++ b/source/gameengine/VideoTexture/VideoDeckLink.h
@@ -155,7 +155,7 @@ public:
 	virtual ~TextureTransfer() { }
 
 	virtual void PerformTransfer() = 0;
-private:
+protected:
 	static bool _PinBuffer(void *address, u_int size);
 	static void _UnpinBuffer(void* address, u_int size);
 };




More information about the Bf-blender-cvs mailing list