[Bf-blender-cvs] [a90ee78] decklink: BGE: Add documentation for decklink support in VideoTexture.
Benoit Bolsee
noreply at git.blender.org
Wed Nov 11 18:43:27 CET 2015
Commit: a90ee7828ea15989ad3050b1044a1d08b7aa025f
Author: Benoit Bolsee
Date: Wed Nov 11 18:40:03 2015 +0100
Branches: decklink
https://developer.blender.org/rBa90ee7828ea15989ad3050b1044a1d08b7aa025f
BGE: Add documentation for decklink support in VideoTexture.
===================================================================
A doc/python_api/examples/bge.texture.2.py
M doc/python_api/rst/bge.texture.rst
===================================================================
diff --git a/doc/python_api/examples/bge.texture.2.py b/doc/python_api/examples/bge.texture.2.py
new file mode 100644
index 0000000..0abbfe1
--- /dev/null
+++ b/doc/python_api/examples/bge.texture.2.py
@@ -0,0 +1,154 @@
+"""
+Video Capture with DeckLink
++++++++++++++++++++++++++++
+Video frames captured with DeckLink cards have pixel formats that are not directly usable by OpenGL,
+they must be processed by a shader. Two shaders are presented here, for the 'r210' and 'v210' pixel
+formats:
+"""
+import bge
+from bge import logic
+from bge import texture as vt
+
+fragment_shaders = {
+'r210': """
+#version 130
+uniform usampler2D tex;
+// stereo = 1.0 if 2D image, =0.5 if 3D (left eye below, right eye above)
+uniform float stereo;
+// eye = 0.0 for the left eye, 0.5 for the right eye
+uniform float eye;
+
+void main(void)
+{
+ vec4 color;
+ unsigned int r;
+ float tx, ty;
+ tx = gl_TexCoord[0].x;
+ ty = eye+gl_TexCoord[0].y*stereo;
+ r = texture(tex, vec2(tx, ty)).r;
+ color.b = float((((r >> 24U)&0xFFU)+((r>>8U)&0x300U))-64U)*0.001136364;
+ color.g = float((((r >> 18U)&0x3FU)+((r>>2U)&0x3C0U))-64U)*0.001136364;
+ color.r = float((((r >> 12U)&0x0FU)+((r<<4U)&0x3F0U))-64U)*0.001136364;
+ // Set alpha to 0.7 for partial transparency when GL_BLEND is enabled
+ color.a = 0.7;
+ gl_FragColor = color;
+}
+""",
+
+'v210':"""
+#version 130
+uniform usampler2D tex;
+// stereo = 1.0 if 2D image, =0.5 if 3D (left eye below, right eye above)
+uniform float stereo;
+// eye = 0.0 for the left eye, 0.5 for the right eye
+uniform float eye;
+
+void main(void)
+{
+ vec4 color;
+ float tx, ty;
+ float width, sx, dx, Y, U, V, bx;
+ unsigned int w0, w1, w2, w3;
+ int px;
+
+ tx = gl_TexCoord[0].x;
+ ty = eye+gl_TexCoord[0].y*stereo;
+ // size of the texture (=real size * 2/3)
+ width = float(textureSize(tex, 0).x);
+ // to sample macro pixels (6 pixels in 4 words)
+ sx = tx*width*0.25+0.05;
+ // index of display pixel in the macro pixel 0..5
+ px = int(floor(fract(sx)*6.0));
+ // increment as we sample the macro pixel
+ dx = 1.0/width;
+ // base x coord of macro pixel
+ bx = (floor(sx)+0.01)*dx*4.0;
+ // load the 4 words components of the macro pixel
+ w0 = texture(tex, vec2(bx, ty)).r;
+ w1 = texture(tex, vec2(bx+dx, ty)).r;
+ w2 = texture(tex, vec2(bx+dx*2.0, ty)).r;
+ w3 = texture(tex, vec2(bx+dx*3.0, ty)).r;
+ switch (px) {
+ case 0:
+ case 1:
+ U = float( w0 &0x3FFU);
+ V = float((w0>>20U)&0x3FFU);
+ break;
+ case 2:
+ case 3:
+ U = float((w1>>10U)&0x3FFU);
+ V = float( w2 &0x3FFU);
+ break;
+ default:
+ U = float((w2>>20U)&0x3FFU);
+ V = float((w3>>10U)&0x3FFU);
+ break;
+ }
+ switch (px) {
+ case 0:
+ Y = float((w0>>10U)&0x3FFU);
+ break;
+ case 1:
+ Y = float( w1 &0x3FFU);
+ break;
+ case 2:
+ Y = float((w1>>20U)&0x3FFU);
+ break;
+ case 3:
+ Y = float((w2>>10U)&0x3FFU);
+ break;
+ case 4:
+ Y = float( w3 &0x3FFU);
+ break;
+ default:
+ Y = float((w3>>20U)&0x3FFU);
+ break;
+ }
+ Y = (Y-64.0)*0.001141553;
+ U = (U-64.0)*0.001116071-0.5;
+ V = (V-64.0)*0.001116071-0.5;
+ color.r = Y + 1.5748 * V;
+ color.g = Y - 0.1873 * U - 0.4681 * V;
+ color.b = Y + 1.8556 * U;
+ color.a = 0.7;
+ gl_FragColor = color;
+}
+"""
+}
+
+#
+# Helper function to attach a pixel shader to the material that receives the video frame.
+#
+def add_shader(obj, pixel, matId, is_3D):
+ if pixel in fragment_shaders:
+ frag = fragment_shaders[pixel]
+ mat = obj.meshes[0].materials[matId]
+ shader = mat.getShader()
+ if shader != None and not shader.isValid():
+ shader.setSource("", frag, 1)
+ shader.setUniform1i("tex", 0)
+ shader.setUniformEyef("eye")
+ shader.setUniform1f("stereo", 0.5 if is_3D else 1.0);
+
+#
+# To be called once to initialize the object
+#
+def init(cont):
+ obj = cont.owner
+ if not "video" in obj:
+ matId = vt.materialID(obj, 'IMvideo.png')
+ add_shader(obj, 'r210', matId, True)
+ tex = vt.Texture(obj, matId)
+ tex.source = vt.VideoDeckLink("HD1080p24/r210/3D", 0)
+ tex.source.play()
+ obj["video"] = tex
+
+#
+# To be called on every frame
+#
+def play(cont):
+ obj = cont.owner
+ try:
+ obj["video"].refresh(True)
+ except:
+ pass
diff --git a/doc/python_api/rst/bge.texture.rst b/doc/python_api/rst/bge.texture.rst
index bb30551..093e45e 100644
--- a/doc/python_api/rst/bge.texture.rst
+++ b/doc/python_api/rst/bge.texture.rst
@@ -51,6 +51,13 @@ When the texture object is deleted, the new texture is deleted and the old textu
:lines: 8-
+.. include:: ../examples/bge.texture.2.py
+ :start-line: 1
+ :end-line: 6
+
+.. literalinclude:: ../examples/bge.texture.2.py
+ :lines: 8-
+
*************
Video classes
*************
@@ -761,7 +768,166 @@ Image classes
:type: bool
+.. class:: VideoDeckLink(format, capture=0)
+
+ Image source from an external video stream captured with a DeckLink video card from
+ Black Magic Design.
+ Before this source can be used, a DeckLink hardware device must be installed, it can be a PCIe card
+ or a USB device, and the 'Desktop Video' software package (version 10.4 or above must be installed)
+ on the host as described in the DeckLink documentation.
+ If in addition you have a recent nVideo Quadro card, you can benefit from the 'GPUDirect' technology
+ to push the captured video frame very efficiently to the GPU. For this you need to install the
+ 'DeckLink SDK' version 10.4 or above and copy the 'dvp.dll' runtime library to Blender's
+ installation directory or to any other place where Blender can load a DLL from.
+
+ :arg format: string describing the video format to be captured.
+ :type format: str
+ :arg capture: Card number from which the input video must be captured.
+ :type capture: int
+
+ The format argument must be written as “<displayMode>/<pixelFormat>[/3D]” where <displayMode>
+ describes the frame size and rate and <pixelFormat> the encoding of the pixels.
+ The optional /3D suffix is to be used if the video stream is stereo with a left and right eye feed.
+ The valid <displayMode> values are copied from the 'BMDDisplayMode' enum in the DeckLink API
+ without the 'bmdMode' prefix. In case a mode that is not in this list is added in a later version
+ of the SDK, it is also possible to specify the 4 letters of the internal code for that mode.
+ You will find the internal code in the DeckLinkAPIModes.h file that is part of the SDK.
+ Here is for reference the full list of supported display modes with their equivalent internal code:
+ * NTSC 'ntsc'
+ * NTSC2398 'nt23'
+ * PAL 'pal '
+ * NTSCp 'ntsp'
+ * PALp 'palp'
+ HD 1080 Modes:
+ * HD1080p2398 '23ps'
+ * HD1080p24 '24ps'
+ * HD1080p25 'Hp25'
+ * HD1080p2997 'Hp29'
+ * HD1080p30 'Hp30'
+ * HD1080i50 'Hi50'
+ * HD1080i5994 'Hi59'
+ * HD1080i6000 'Hi60'
+ * HD1080p50 'Hp50'
+ * HD1080p5994 'Hp59'
+ * HD1080p6000 'Hp60'
+ HD 720 Modes:
+ * HD720p50 'hp50'
+ * HD720p5994 'hp59'
+ * HD720p60 'hp60'
+ 2k Modes
+ * 2k2398 '2k23'
+ * 2k24 '2k24'
+ * 2k25 '2k25'
+ 4k Modes
+ * 4K2160p2398 '4k23'
+ * 4K2160p24 '4k24'
+ * 4K2160p25 '4k25'
+ * 4K2160p2997 '4k29'
+ * 4K2160p30 '4k30'
+ * 4K2160p50 '4k50'
+ * 4K2160p5994 '4k59'
+ * 4K2160p60 '4k60'
+ Most of names are self explanatory. If necessary refer to the DeckLink API documentation for more information.
+
+ Similarly, <pixelFormat> is copied from the BMDPixelFormat enum.
+ Here is for reference the full list of supported pixel format and their equivalent internal code:
+ * 8BitYUV '2vuy'
+ * 10BitYUV 'v210'
+ * 8BitARGB * no equivalent code *
+ * 8BitBGRA 'BGRA'
+ * 10BitRGB 'r210'
+ * 12BitRGB 'R12B'
+ * 12BitRGBLE 'R12L'
+ * 10BitRGBXLE 'R10l'
+ * 10BitRGBX 'R10b'
+ Refer to the DeckLink SDK documentation for a full description of these pixel format.
+ It is important to understand them as the decoding of the pixels is NOT done in VideoTexture
+ for performance reason. Instead a specific shader must be used to decode the pixel in the GPU.
+ Only the ' 8BitARGB' and '8BitBGRA' pixel format have an equivalent in OpenGL.
+ Other formats are sent to the GPU as a 'GL_RED_INTEGER' texture (i.e. a texture with only the
+ red channel coded as an unsigned 32 bit integer). This helps extracting the color channels
+ in a shader.
+
+ Example: “HD1080p24/10BitRGB/3D” is equivalent to “24ps/r210/3D” and represents a full HD stereo feed at 24 frame per second.
+
+ Although video format auto detection is possible with certain DeckLink devices, the corresponding
+ API is NOT implemented in the BGE. Therefore it is important to specify the format string that
+ matches exactly the video feed. If the format is wrong, no frame will be captured.
+ It should be noted that the pixel format that you need to specify is not necessarily the actual
+ format in the video feed. For example, the 4K Extreme card delivers 8bit RGBs pixels in the
+ '10BitRGB' format. Use the 'Media Express' application included in 'Desktop Video' to discover
+ which pixel format works for a particular video stream.
+
+ .. attribute:: status
+
+ Status of the capture: 1=ready to use, 2=capturing, 3=stopped
+
+ :type: int
+ .. attribute:: framerate
+
+ Capture frame rate as computed from the video format.
+
+ :type: float
+
+ .. attribute:: valid
+
+ Tells if the image attribute can be used to retrieve the image.
+ Always False in this implementation (the image is not available at python level)
+
+ :type: bool
+
+ .. attribute:: image
+
+ The image data. Always None in this implementation.
+
+ :type: :class:`~bgl.Buffer` or None
+
+ .. attribute:: size
+
+ The size of the frame in pixel.
+ Stereo frames have double the height of the video frame, i.e. 3D is
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list