Video Texturing Primer
Overview
VTP is a small suite of applications to demonstrate the different ways to do video texture mapping on the O2, Octane, and Onyx2 systems from Silicon Graphics. This code was written for the express purpose of teaching different approaches to video texture mapping. These examples are distilled down to a minimal set of required logic to accomplish the task. You will find very little error checking in these code examples which of course is not the way to code real applications. What you will find is only the necessary steps and ordering to perform video texturing on each of the forementioned systems. The longest example code is the fast path video texturing example for O2. This weighs in at 330 lines. All remaining examples are 200 lines of code or less. I expect this will be a welcome thing for those unfamiliar with video, texture mapping, or digital media buffers.
Included in this suite is minvideoin. This is a minimalist source example of the required logic to create the well known "videoin" application.
There is a common method that can be used to do video texture mapping on O2, Octane, and Onyx2 with only a few exceptions. This code is illustrated in vtSGI.c++. The way these systems are designed makes a great deal of difference on how well they perform with this cross platform solution. The results of running this application on DIVO with Onyx2 is excellent as it employs the expected method of downloading video frames through the host to graphics interface.
On O2, Octane, and Onyx2 with Sirius Video the cross platform solution performs well but does not fully use the capacity of these architectures. O2 yields maximum performance when the video fields are delivered to a digital media buffer that in turn is used by OpenGL to do texture mapping. With Octane Video and Sirius Video, there is a dedicated flat cable that allows direct transfer of the video fields to the host graphics hardware. The programmatic interface to this type of video texture mapping is handled through the video source extension to OpenGL.
Common Logic (vtSGI.c++)
In all source examples, fields are selected for rendering by a call to vlSetControl on the video drain node setting the integer value to: VL_CAPTURE_NONINTERLEAVED. There is a trade off for deciding to use fields vs frames. Fields have the advantage that they are smaller therefore the required texture size to hold them can be smaller. Recalling that textures must have dimensionality that is a power of 2 in all dimensions (S and T in this case) results in defining a texture must be 1024x256 for fields and 1024x512 for frames on all the forementioned hardware. On graphics systems with a fixed amount of texture memory (Impact, Infinite Reality) it may be advantageous to have a smaller texture definition. The smaller a bound texture the less susceptible it is to being paged out to host memory by the texture manager because of overcommitment of the texture memory. This save and restore mechanism of a bound texture may result in a loss of video frames.
Using fields has the slight performance disadvantage on systems that required downloading through a host/graphics interface because the overhead associated with setting up a direct memory access is slightly less in the frame case. Because there is some overhead associated with setting up a DMA regardless of the size of the transfer the effective bandwidth is higher for larger transfers (i.e. frames).
So, now that we know that there is no great speed/efficiency advantage for using fields vs frames we look at quality. If rendering fields into our textures we can use the frame aspect for our spatial coordinates on the video texture mapped polygon to get full frame video. Having the spatial aspect correspond to frame size yet the texture aspect correspond to field size yields a linearly interpolated field in the T dimension that approximates a frame. Therefore at any instant in time only half the available resolution for a frame is rendered.
We can ask the video library to deliver frames by doing a vlSetControl on the video drain node setting the integer value to: VL_CAPTURE_INTERLEAVED. Because fields are temporally distinct the effect of asking for an interleaved frame can result in tearing artifacts. These artifacts are most evident when there is a good deal of motion in the scene resulting in larger differences between fields.
The common logic for all of these source examples follows these steps:
O2 Specific Implementation (vtO2.c++)
Some terminology for the following discussion is in order. A digital media pixel buffer (dmPbuffer) is a glx drawable that can be used for OpenGL rendering of digital media data. A digital media buffer (dmbuffer) is space reserved in memory for the transport of digital media data. This transport can be used by some of the various libraries that operate on digital media: VL, IC, CL, and GL.
The fastest implementation on O2 requires use of dmPbuffers and dmbuffers. Creating a digital media pbuffer requires choosing an appropriate frame buffer configuration and creating a glx context that is compatible with the fbconfig.
Most of the work specific to dmbuffers is in creating and configuring the dmbuffer pool. This is the area from which dmbuffers can be allocated and is configured according to the size, number, orientation, and layout of the dmbuffers it will contain. The good news is that for video texturing this configuration is done for the most part in 2 library calls: vlDMPoolGetParams and dmBufferGetGLPoolParams. What is not done by these two calls is setting the appropriate number of buffers required by both VL, GL and the application. Because these functions have no knowledge of one another, the number of buffers must be explicitly determined by:
The pool can then be registered with the VL by calling: vlDMPoolRegister. This in effect allows the VL to use buffers in the pool as the destination of incoming video frames or fields.
The strategy of using dmPbuffers with dmbuffers allows an association between GL and VL. As new fields of data arrive from the video server the contents of the texture needs to be updated. These new fields of data will be contained in a dmbuffer selected by VL from the dmbuffer pool we set up. In order to use this information in OpenGL we associate the dmbuffer with the dmPbuffer created earlier by calling glXAssociateDMPbufferSGIX. The texture can then be redefined by making the dmPbuffer the read source for the new texture definition using glXMakeCurrentRead. Once the read source is established a call to glCopyTexSubImage2DEXT is made to effectively copy the contents of the new field to the texture.
Once this work has been done, the geometry in the scene can be texture mapped in the usual manner.
Octane / Sirius Implementation (vtOctane.c++ / vtSirius.c++)
The only difference between the Octane and Sirius implementation is a result of a constraint with Impact graphics. This constraint requires that subtexture definitions are right aligned on 32 texel boundaries. For simplicity, both the Sirius and Octane implementations in vtp are aligned as such.
Video Texture Mapping on these systems is fastest when implemented with the video source extension. The video source extension is used by:
The two texture bindings are used as a double buffering scheme whereby the VL can be using one binding for loading the next field and the other can be used by GL for texture mapping.
Similar to the fast implementation on O2, glCopyTexSubImage2DEXT is used to copy from texels from an alternate read source to update the texture. In this case, the alternate read source is the video source created by glXCreateGLXVideoSourceSGIX.
DIVO Implementation (vtDivo.c++)
The DIVO implementation is the simplest of all in that it requires only that you pass the video field data through the host interface. This method requires no set up of a fast read source and is the method used for the all platform implementation: vtSGI.c++.
Vtdivo was written separately and contains none of the IRIX 6.3 specific logic that vtSGI.c++ does. It is interesting and informative to compare these two source files and note the subtle differences.
minVideoIn.c++
This is a bare bones source file of less than 100 lines of code. Shows all the essential logic for creating the well know "videoin" application. Very good source introduction to VL.
Files
vtSGI.c++ | Cross platform source file that must be recompiled when going from 6.3 to non 6.3 systems and vice versa. |
vtO2.c++ | O2 fast path implementation. |
vtOctane.c++ | Octane fast path implementation. |
vtSirius.c++ | Sirius fast path implementation. Nearly identical to vtOctane.c++ |
vtDivo.c++ | DIVO fast path implementation. Very similar to vtSGI.c++ |
minVideoIn.c++ | Minimalist code to doing the simple VideoIn application |
Other References
For other source examples, see vidtotex.c which is found in the dmedia_dev.src.examples. You may need to ask the assistance of your administrator for installing this.
For written documentation on DM buffers and using VL check out the Video Lurkers Guide from Silicon Graphics.
The digital media programmers guide for IRIX 6.2 and IRIX 6.3 differ. For a basic introduction to VL, the 6.2 guide is better.
Author: John Rosasco jdr@sgi.com
Last Updated: May 19, 1997