[Bf-blender-cvs] [a2df27f] decklink: VideoDeckLink: wip, card opening done, GPUdirect tbd.

Benoit Bolsee noreply at git.blender.org
Mon Mar 23 23:29:01 CET 2015


Commit: a2df27ff89fb5b7cb91302f38af16bd040568c7c
Author: Benoit Bolsee
Date:   Mon Mar 23 23:27:09 2015 +0100
Branches: decklink
https://developer.blender.org/rBa2df27ff89fb5b7cb91302f38af16bd040568c7c

VideoDeckLink: wip, card opening done, GPUdirect tbd.

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

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 d7a331c..e0fceda 100644
--- a/source/gameengine/VideoTexture/VideoDeckLink.cpp
+++ b/source/gameengine/VideoTexture/VideoDeckLink.cpp
@@ -35,19 +35,92 @@
 #define __STDC_CONSTANT_MACROS
 #endif
 #include <stdint.h>
+#include <string.h>
 
 #include "VideoDeckLink.h"
-#include "GL/glew.h"
 #include "dvpapi_gl.h"
 
 #include "MEM_guardedalloc.h"
 #include "PIL_time.h"
 
-#include <string>
-
 #include "Exception.h"
 
+static struct 
+{
+	const char *name;
+	BMDDisplayMode mode;
+} sModeStringTab[] = {
+	{ "NTSC", bmdModeNTSC },
+	{ "NTSC2398", bmdModeNTSC2398 },
+	{ "PAL", bmdModePAL },
+	{ "NTSCp", bmdModeNTSCp },
+	{ "PALp", bmdModePALp },
+
+	/* HD 1080 Modes */
+
+	{ "HD1080p2398", bmdModeHD1080p2398 },
+	{ "HD1080p24", bmdModeHD1080p24 },
+	{ "HD1080p25", bmdModeHD1080p25 },
+	{ "HD1080p2997", bmdModeHD1080p2997 },
+	{ "HD1080p30", bmdModeHD1080p30 },
+	{ "HD1080i50", bmdModeHD1080i50 },
+	{ "HD1080i5994", bmdModeHD1080i5994 },
+	{ "HD1080i6000", bmdModeHD1080i6000 },
+	{ "HD1080p50", bmdModeHD1080p50 },
+	{ "HD1080p5994", bmdModeHD1080p5994 },
+	{ "HD1080p6000", bmdModeHD1080p6000 },
+
+	/* HD 720 Modes */
+
+	{ "HD720p50", bmdModeHD720p50 },
+	{ "HD720p5994", bmdModeHD720p5994 },
+	{ "HD720p60", bmdModeHD720p60 },
+
+	/* 2k Modes */
+
+	{ "2k2398", bmdMode2k2398 },
+	{ "2k24", bmdMode2k24 },
+	{ "2k25", bmdMode2k25 },
+
+	/* DCI Modes (output only) */
+
+	{ "2kDCI2398", bmdMode2kDCI2398 },
+	{ "2kDCI24", bmdMode2kDCI24 },
+	{ "2kDCI25", bmdMode2kDCI25 },
+
+	/* 4k Modes */
+
+	{ "4K2160p2398", bmdMode4K2160p2398 },
+	{ "4K2160p24", bmdMode4K2160p24 },
+	{ "4K2160p25", bmdMode4K2160p25 },
+	{ "4K2160p2997", bmdMode4K2160p2997 },
+	{ "4K2160p30", bmdMode4K2160p30 },
+	{ "4K2160p50", bmdMode4K2160p50 },
+	{ "4K2160p5994", bmdMode4K2160p5994 },
+	{ "4K2160p60", bmdMode4K2160p60 },
+	// sentinel
+	{ NULL }
+};
+
 
+static struct 
+{
+	const char *name;
+	BMDPixelFormat format;
+} sFormatStringTab[] = {
+	{ "8BitYUV", bmdFormat8BitYUV },
+	{ "10BitYUV", bmdFormat10BitYUV },
+	{ "8BitARGB", bmdFormat8BitARGB },
+	{ "8BitBGRA", bmdFormat8BitBGRA },
+	{ "10BitRGB", bmdFormat10BitRGB },
+	{ "12BitRGB", bmdFormat12BitRGB },
+	{ "12BitRGBLE", bmdFormat12BitRGBLE },
+	{ "10BitRGBXLE", bmdFormat10BitRGBXLE },
+	{ "10BitRGBX", bmdFormat10BitRGBX },
+	// sentinel
+	{ NULL }
+};
+	
 // macro for exception handling and logging
 #define CATCH_EXCP catch (Exception & exp) \
 { exp.report(); m_status = SourceError; }
@@ -55,13 +128,51 @@
 // class RenderVideo
 
 // constructor
-VideoDeckLink::VideoDeckLink (HRESULT * hRslt) : VideoBase()
+VideoDeckLink::VideoDeckLink (HRESULT * hRslt) : VideoBase(),
+mDLInput(NULL),
+mUse3D(false),
+mHasDvp(false),
+mHasAMDPinnedMemory(false),
+mFastTransferAvailable(false),
+mFrameWidth(0),
+mFrameHeight(0),
+mTextureWidth(0),
+mTextureHeight(0),
+mUnpinnedTextureBuffer(0),
+mCaptureTexture(0),
+mpAllocator(NULL),
+mpCaptureDelegate(NULL),
+mpCacheFrame(NULL)
 {
+	mDisplayMode = (BMDDisplayMode)0;
+	mPixelFormat = (BMDPixelFormat)0;
+	pthread_mutex_init(&mCacheMutex, NULL);
 }
 
 // destructor
 VideoDeckLink::~VideoDeckLink ()
 {
+	if (mDLInput != NULL)
+	{
+		// Cleanup for Capture
+		mDLInput->SetCallback(NULL);
+		mDLInput->Release();
+		mDLInput = NULL;
+	}
+	if (mpAllocator) 
+	{
+		delete mpAllocator;
+		mpAllocator = NULL;
+	}
+	if (mpCaptureDelegate)
+	{
+		delete mpCaptureDelegate;
+		mpCaptureDelegate = NULL;
+	}
+	if (mpCacheFrame)
+		mpCacheFrame->Release();
+	if (mUnpinnedTextureBuffer)
+		glDeleteBuffers(1, &mUnpinnedTextureBuffer);
 }
 
 void VideoDeckLink::refresh(void)
@@ -76,21 +187,220 @@ bool VideoDeckLink::release()
 	return true;
 }
 
+ExceptionID SourceVideoOnlyCapture, VideoDeckLinkBadFormat, VideoDeckLinkOpenCard, VideoDeckLinkInternalError;
+ExpDesc SourceVideoOnlyCaptureDesc(SourceVideoOnlyCapture, "This video source only allows live capture");
+ExpDesc VideoDeckLinkBadFormatDesc(VideoDeckLinkBadFormat, "Invalid or unsupported capture format, should be <mode>/<pixel>[/3D]");
+ExpDesc VideoDeckLinkOpenCardDesc(VideoDeckLinkOpenCard, "Cannot open capture card, check if driver installed");
+ExpDesc VideoDeckLinkInternalErrorDEsc(VideoDeckLinkInternalError, "DeckLink API internal error, please report");
 
 // open video file
 void VideoDeckLink::openFile (char *filename)
 {
-	// open base class
-	VideoBase::openFile(filename);
-
+	// only live capture on this device
+	THRWEXCP(SourceVideoOnlyCapture, S_OK);
 }
 
 
 // open video capture device
-void VideoDeckLink::openCam (char *file, short camIdx)
+void VideoDeckLink::openCam (char *format, short camIdx)
 {
+	IDeckLinkDisplayModeIterator*	pDLDisplayModeIterator;
+	BMDDisplayModeSupport			modeSupport;
+	IDeckLinkDisplayMode*			pDLDisplayMode;
+	IDeckLinkIterator*				pIterator;
+	BMDTimeValue					frameDuration;
+	BMDTimeScale					frameTimescale;
+	IDeckLink*						pDL;
+	u_int displayFlags, inputFlags; 
+	char *pPixel, *p3D;
+	size_t len;
+	int i;
+
+	// open the card
+	pIterator = BMD_CreateDeckLinkIterator();
+	pDL = NULL;
+	if (pIterator) 
+	{
+		i = 0;
+		while (pIterator->Next(&pDL) == S_OK) 
+		{
+			if (i == camIdx) 
+			{
+				if (pDL->QueryInterface(IID_IDeckLinkInput, (void**)&mDLInput) != S_OK)
+					mDLInput = NULL;
+				break;
+			}
+			i++;
+		}
+	}
+	if (!mDLInput)
+		THRWEXCP(VideoDeckLinkOpenCard, S_OK);
+
+	// format is constructed as <displayMode>/<pixelFormat>[/3D]
+	// <displayMode> takes the form of BMDDisplayMode identifier minus the 'bmdMode' prefix.
+	//               This implementation understands all the modes defined in SDK 10.3.1 but you can alternatively
+	//               use the 4 characters internal representation of the mode (e.g. 'HD1080p24' == '24ps')
+	// <pixelFormat> takes the form of BMDPixelFormat identifier minus the 'bmdFormat' prefix.
+	//               This implementation understand all the formats defined in SDK 10.32.1 but you can alternatively
+	//               use the 4 characters internal representation of the format (e.g. '10BitRGB' == 'r210')
+	// Not all combinations of mode and pixel format are possible and it also depends on the card!
+	// Use /3D postfix if you are capturing a 3D stream with frame packing
+	// Example: To capture FullHD 1920x1080 at 24Hz with 3D packing and 4:4:4 10 bits RGB pixel format, use
+	// "HD1080p24/10BitRGB/3D"  (same as "24ps/r210/3D")
+	// (this will be the normal capture format for FullHD on the DeckLink 4k extreme)
+
+	if ((pPixel = strchr(format, '/')) == NULL ||
+		((p3D = strchr(pPixel + 1, '/')) != NULL && strcmp(p3D, "/3D")))
+		THRWEXCP(VideoDeckLinkBadFormat, S_OK);
+	mUse3D = (p3D) ? true : false;
+	// read the mode
+	len = (size_t)(pPixel - format);
+	pPixel++;
+	for (i = 0; sModeStringTab[i].name != NULL; i++) {
+		if (strlen(sModeStringTab[i].name) == len &&
+			!strncmp(sModeStringTab[i].name, format, len)) 
+		{
+			mDisplayMode = sModeStringTab[i].mode;
+			break;
+		}
+	}
+	if (!mDisplayMode) 
+	{
+		if (len != 4)
+			THRWEXCP(VideoDeckLinkBadFormat, S_OK);
+		// assume the user entered directly the mode value as a 4 char string
+		mDisplayMode = (BMDDisplayMode)((((u_int)format[0]) << 24) + (((u_int)format[1]) << 16) + (((u_int)format[2]) << 8) + ((u_int)format[3]));
+	}
+	// read the pixel
+	len = ((mUse3D) ? (size_t)(p3D - pPixel) : strlen(pPixel));
+	for (i = 0; sFormatStringTab[i].name != NULL; i++) 
+	{
+		if (strlen(sFormatStringTab[i].name) == len &&
+			!strncmp(sFormatStringTab[i].name, format, len)) 
+		{
+			mPixelFormat = sFormatStringTab[i].format;
+			break;
+		}
+	}
+	if (!mPixelFormat) 
+	{
+		if (len != 4)
+			THRWEXCP(VideoDeckLinkBadFormat, S_OK);
+		// assume the user entered directly the mode value as a 4 char string
+		mPixelFormat = (BMDPixelFormat)((((u_int)pPixel[0]) << 24) + (((u_int)pPixel[1]) << 16) + (((u_int)pPixel[2]) << 8) + ((u_int)pPixel[3]));
+	}
+	
+	
+	// check if display mode and pixel format are supported
+	if (mDLInput->GetDisplayModeIterator(&pDLDisplayModeIterator) != S_OK)
+		THRWEXCP(VideoDeckLinkInternalError, S_OK);
+
+	pDLDisplayMode = NULL;
+	displayFlags = (mUse3D) ? bmdDisplayModeSupports3D : 0;
+	inputFlags = (mUse3D) ? bmdVideoInputDualStream3D : bmdVideoInputFlagDefault;
+	while (pDLDisplayModeIterator->Next(&pDLDisplayMode) == S_OK) 
+	{
+		if (   pDLDisplayMode->GetDisplayMode() == mDisplayMode 
+			&& (pDLDisplayMode->GetFlags() & displayFlags) == displayFlags
+			&& mDLInput->DoesSupportVideoMode(mDisplayMode, mPixelFormat, inputFlags, &modeSupport, NULL) == S_OK
+			&& modeSupport == bmdDisplayModeSupported)
+			break;
+		pDLDisplayMode->Release();
+		pDLDisplayMode = NULL;
+	}
+	pDLDisplayModeIterator->Release();
+
+	if (pDLDisplayMode == NULL)
+		THRWEXCP(VideoDeckLinkBadFormat, S_OK);
+
+	mFrameWidth = pDLDisplayMode->GetWidth();
+	mFrameHeight = pDLDisplayMode->GetHeight();
+	mTextureHeight = (mUse3D) ? 2 * mFrameHeight : mFrameHeight;
+	pDLDisplayMode->GetFrameRate(&frameDuration, &frameTimescale);
+	// for information, in case the application wants to know
+	m_size[0] = mFrameWidth;
+	m_size[1] = mTextureHeight;
+	m_frameRate = (float)frameTimescale / (float)frameDuration;
+
+	switch (mPixelFormat)
+	{
+	case bmdFormat8BitYUV:
+		// 2 pixels per word
+		mTextureStride = mFrameWidth * 2;
+		mTextureWidth = mFrameWidth / 2;
+		mTextureFormat = GL_RED_INTEGER;
+		mTextureType = GL_UNSIGNED_INT;
+		break;
+	case bmdFormat10BitYUV:
+		// 6 pixels in 4 words, rounded to 48 pixels
+		mTextureStride = ((mFrameWidth + 47) / 48) * 128;
+		mTextureWidth = ((mFrameWidth + 5) / 6) * 4;
+		mTextureFormat = GL_RED_INTEGER;
+		mTextureType = GL_UNSIGNED_INT;
+		break;
+	case bmdFormat8BitARGB:
+		mTextureStride = mFrameWidth * 4;
+		mTextureWidth = mFrameWidth;
+		mTextureFormat = GL_BGRA;
+		mTextureType = GL_UNSIGNED_INT_8_8_8_8;
+		break;
+	case bmdFormat8BitBGRA:
+		mTextureStride = mFrameWidth * 4;
+		mTextureWidth = mFrameWidth;
+		mTextureFormat = GL_BGRA;
+		mTextureType = GL_UNSIGNED_INT_8_8_8_8_REV;
+		break;
+	case bmdFormat10BitRGBXLE:
+	case bmdFormat10BitRGBX:
+	case bmdFormat10BitRGB:
+		mTextureStride = ((mFrameWidth + 63) / 64) * 256;
+		mTextureWidth = mFrameWidth;
+		mTextur

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list