[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