Support This Site | This hobby site is supported by readers like you. To guarantee future updates, please support the site in one of these ways: |
![]() | Use your credit card or PayPal to donate in support of the site. |
![]() | Use this link to Amazon—you pay the same, I get 4%. |
![]() | Learn Thai with my Talking Thai-English-Thai Dictionary app: iOS, Android, Windows. |
![]() | Experience Thailand richly with my Talking Thai-English-Thai Phrasebook app. |
![]() | Visit China easily with my Talking Chinese-English-Chinese Phrasebook app. |
![]() | I co-authored this bilingual cultural guide to Thai-Western romantic relationships. |
Submit This Site | Like what you see? Help spread the word on social media: | |||
| ||||
Note: Updated Lurker's Guide available (but not this page!)This page belongs to the old 1990s SGI Lurker's Guide. As of 2008, several of the Lurker's Guide pages have been updated for HDTV and for modern OS platforms like Windows and Mac. This particular page is not one of those, but you can see what new stuff is available here. Thanks!
This document supplements the material in the "IRIS Media Libraries Programming Guide" (hereinafter, "the Guide"). It adds information about the VL that I think is missing or wrong in the Guide. It doesn't attempt to answer all remaining questions about the VL, or to be a complete reference. This is merely the information that I figured out while making InPerson work on vino, ev1, ev3, and sirius video for IRIX 5.3 and 6.2. Chris updated this document for mvp and IRIX 6.3. This information applies only to those VL video devices, and not to any other present or future VL video devices (it does not yet completely reflect cosmo2 and divo, for example).
This document does not represent SGI, and is not an official SGI publication. The entire contents of this document are my personal observations, and/or opinions, and all errors and opinions in it are mine alone. SGI makes no guarantees about anything in this document. Neither do I. You use it at your own risk. Additional disclaimers below.
Some topics NOT discussed in this page include:The VL_SIZE control on the video source node is a read-only control. The x and y values returned by this control are affected by the setting of the VL_TIMING control on the video source node. The x and y values of this control are not, in general, affected by the settings of any controls in the memory drain node, including VL_ZOOM, VL_SIZE, and VL_CAP_TYPE.
The x component value of this control reveals the width, in pixels, of the unzoomed, unclipped video input images (fields or frames). The meaning of the y component value of the video source node's VL_SIZE control depends on the video device.
On sirius, an application uses VL_PACKING on the memory node to specify the packing, and VL_FORMAT on the memory node to specify colorspace. If necessary, sirius will do colorspace conversion. Sirius is the only device where VL_FORMAT even applies to memory node.
On divo, an application uses VL_PACKING on the memory node to specify the packing, and VL_COLORSPACE on the memory node to specify colorspace. If necessary, divo will do colorspace conversion. This is a new API which should be inherited by all new VL devices from divo and beyond.
For complete information on pixel packings and colorspaces, check out The Pixel Rosetta Stone: Packings and Colorspaces.
The VL_PACKING_YVYU_422_8 packing is the only packing that is natively supported in hardware (requiring no software conversion) on all VL video devices. The packing always uses 4:2:2 sampling, and the default colorspace for this packing is always headroom-range. See The Pixel Rosetta Stone: Packings and Colorspaces for definitions of these terms.
On sirius, this control is read-only, and is permanently set to VL_CAPTURE_NONINTERLEAVED. Each captured buffer contains exactly one field, unclipped, unzoomed.
The possible values are:
On all devices except ev1, this setting of VL_CAP_TYPE will give you one field in each entry of a VLBuffer. The data will always begin with a dominant field (F1 unless otherwise specified by the video device) and it will always alternate between F1 and F2 (see Definitions: F1/F2, Interleave, Field Dominance, and More for definitions of dominance, F1, and F2). If the device has to drop some data, it will drop both an F1 and an F2 (in some order), so that the .../F1/F2/F1/F2/... ordering is maintained. VL_RATE is in fields per second.
On ev1, each VLBuffer entry contains two fields butted up against one another in memory, with the F1 field first in memory and then the F2 field. VL_RATE is in frames per second.
On devices which support it, this setting of VL_CAP_TYPE gives you pairs of fields which have been weaved together in memory to form a complete frame (television picture) from top to bottom. The F1 and F2 fields are placed according to the rules for the video standard being used, as described in Definitions: F1/F2, Interleave, Field Dominance, and More. VL_RATE is in frames per second.
This setting is like VL_CAPTURE_NONINTERLEAVED except you only get F1 fields. VL_RATE is in frames per second.
This setting is like VL_CAPTURE_NONINTERLEAVED except you only get F2 fields. VL_RATE is in frames per second.
There is no single VL_CAP_TYPE that is available, and implemented in the same way, on all VL video devices. VL_CAPTURE_NONINTERLEAVED is available on all devices, but has different meanings on different platforms. VL_CAPTURE_INTERLEAVED, VL_CAPTURE_EVEN_FIELDS, and VL_CAPTURE_ODD_FIELDS are available and common to all VL video devices except sirius.
On all VL video devices except sirius, this control sets the target rate (upper bound) of image buffers per second that will be captured and returned to the application. That is, the VL will not deliver more buffers per second than the rate you specify, but it might deliver less than you specify, especially on ev1.
VL_RATE is in units of buffers per second. That may be frames or fields per second depending on whether each buffer entry has a frame or field in it, which is determined by VL_CAP_TYPE. See VL_CAP_TYPE above for more info.
VL_RATE is a fraction. Both the numerator and denominator must be specified. The usual value for the denominator is 1. Some devices, such as ev1, internally convert the fraction to a whole integer (truncating, not rounding) of images per second, so using values that are equivalent to integer values is the safest thing to do.
Because VL_RATE is a fraction, vlGetControlInfo() cannot be used to obtain the minimum or maximum values for VL_RATE.
Acceptable values are determined from the following table for non-sirius devices:
VL_CAPTURE_NONINTERLEAVED (all devices except ev1 and sirius) | 525 | All multiples of 10 and 12 between 10 and 60 |
625 | All multiples of 10 between 10 and 50 | |
VL_CAPTURE_NONINTERLEAVED (ev1) | 525 | All multiples of 5 and 6 between 5 and 30 |
625 | All multiples of 5 between 5 and 25 | |
VL_CAPTURE_INTERLEAVED, VL_CAPTURE_EVEN_FIELDS, and VL_CAPTURE_ODD_FIELDS | 525 | All multiples of 5 and 6 between 5 and 30 |
625 | All multiples of 5 between 5 and 25 |
With sirius video, this control is read-only. Its value is determined by the setting of the VL_TIMING control on the memory node:
VL_CAPTURE_NONINTERLEAVED | 525 | 60 fields per second |
625 | 50 fields per second |
Vino's VL_RATE cannot be set to a value less than 5/1.
Vino has hardware bugs that affect decimation of images at these decimation factors: 1/4, 1/5, 1/6, 1/7, and 1/8. These bugs include:
Vino:
1/1, 1/2, 1/3 | Implemented in hardware, looks OK. |
1/4, 1/6 | Implemented partially in hardware, partially in software. Looks OK, but slower and uses roughly 10% of an R4600 CPU. |
1/5, 1/7, 1/8 | implemented in hardware. Looks bad. Green shift. |
ev1:
1/1, 1/2, 1/4, 1/8 | Works OK for vid-to-mem |
1/3, 1/5, 1/7 | Works only for vid-to-screen, not vid-to-mem, and only with VL_CAPTURE_INTERLEAVED. |
2/1, 4/1 | Works only for vid-to-screen, not vid-to-mem. |
sirius and ev3:
1/1 | sirius and ev3 don't zoom. |
The VL_SIZE control on the memory drain node determines the number of rows of pixels, and the number of pixels in each row, in each image buffer (field or frame) that the VL returns to the application. If zooming (decimation) is being done, the VL_SIZE control on the memory drain node specifies the size of the image after it has been decimated.
The VL_SIZE control on the memory drain node can be used to "clip" a region out of an image by setting the X and/or Y components to values that are smaller than the size of the captured (and decimated, if applicable) image.
When the (possibly decimated) image is being clipped, the clipped region does not have to come from the upper left hand corner of the (possibly decimated) source image. The VL_OFFSET control on the memory drain node determines the number of top pixel rows to skip and the number of leading pixels to skip in each row to find the first pixel in the (possibly decimated) image to place in the image buffer, the first pixel of the clipping region.
The Guide says, incorrectly, that "VL_OFFSET operates on the unzoomed image; it does not change if the zoom factor is changed.". The truth is that when zooming (decimation) is being used, VL_OFFSET is always in coordinates of the zoomed image. It is as if the entire source image is decimated down, and then the clipping function is applied to the decimated image. The hardware rarely works that way, and usually clips before decimating, but the VL API always specifies the VL_OFFSET in the coordinates of the decimated (virtual) image.
On all VL devices except sirius, the vertical (Y) component of VL_OFFSET may be specified with a negative value. This causes the clipping region to include row of samples taken before the top of the image, e.g. rows from the vertical blanking interval. This feature is usually used with VL_ZOOM of 1/1, since the information in the vertical blanking interval is generally destroyed by a zooming operation.
Because VL_OFFSET is useful for parsing VITC and other vertical interval information, it is useful to know which video line you get at the top of your F1 and F2 buffers for a particular Y value of VL_OFFSET, when you have selected VL_CAPTURE_NONINTERLEAVED and VL_ZOOM=1/1. A VL_OFFSET Y value of 0 gives you F1 and F2 buffers which begin on the following video lines:
Video Standard | vino F1 | vino F2 | ev1 F1 | ev1 F2 | mvp F1 | mvp F2 | ev3 F1 | ev3 F2 |
---|---|---|---|---|---|---|---|---|
525-line | 21 | 284 | 21 | 283 | 21 | 283 | ? | ? |
625-line | 23 | 336 | 23 | 336 | 23 | 336 | ? | ? |
This table uses the line numbers and definitions from Definitions: F1/F2, Interleave, Field Dominance, and More. Note that all the cases except for 525-line F2 fields with vino conform to the diagrams "analog 525, practical digital 525, analog 625, and digital 625" shown in that document.
On vino, ev1, mvp, and ev3, any other VL_OFFSET Y value (positive or negative) slides your buffer up or down the video signal by that many lines. The minimum allowed Y value is device-dependent, but is negative enough to pick up VITC on at least the higher of the recommended lines found in ANSI/SMPTE 12M.
On ev1, when you select VL_CAPTURE_NONINTERLEAVED, each of your buffers contains an F1 and an F2 field butted together. The Y coordinates of VL_OFFSET have strange units which behave like "picture lines" even though this doesn't make sense. Basically, if you would like to shift N lines, set VL_OFFSET's Y coordinate to 2*N.
This document does not cover what ev3's units are because we haven't tested it yet.
The VL imposes these requirements on the values of VL_OFFSET and VL_SIZE:
VL_OFFSET and VL_SIZE cannot be both set in one atomic operation. A change in either component of either control could violate one of the rules above (or below), especially after VL_ZOOM is set to a smaller fraction. It may be necessary to alternately and repeatedly set VL_OFFSET and VL_SIZE until no VLValueOutOfRange errors are reported. See vlSetControlLoop.txt for a code sample that does this.
Every VL video device places additional limitations on the range of acceptable values of VL_SIZE and VL_OFFSET. Each device has different limitations.
An interesting bug: After setting VL_SIZE and/or VL_OFFSET on an ev1 memory drain node, the vertical value read back from the VL_SIZE control is often (always?) one less than the value set into the VL_SIZE control, indicating that the image buffers will contain one less row of pixels than were requested. In this case, the actual size of the buffer returned by ev1 will usually contain the requested number of rows, one more than the value returned in the VL_SIZE control.
Sirius doesn't support preemption. ev1 ellows preemption in some "sync modes" but not in others. When preemption is not allowed, the VL behaves as if the path was in mode VL_LOCK instead of VL_SHARE; preemptions simply don't happen.
When preemption occurs, your program will receive a VlStreamPreempted event. This means the following things:
The VLStreamAvailable events create a race between the preempted programs. The outcome of the race depends on the actions taken by the programs, and also on the device's implementation. Generally, as long as all the programs are attempting shared use of the path, the last caller of vlSetupPaths() wins.
When a program receives the VLStreamAvailable event, to regain the usage of the path's data stream, it should call vlSetupPaths(..., VL_SHARE, VL_SHARE) again. This call to vlSetupPaths() to regain access to the path's data stream can succeed or it can fail. The VLStreamAvailable event does not guarantee that it will succeed. Let's look at these cases separately.
If the call to vlSetupPaths() succeeds, the application should set all the controls for the path to the values they had before it was preempted. Your application, that is now regaining the use of the stream, should not assume that the controls are as they were before the preemption. The preemption caused the usage of the path's controls to become VL_SHARE, so the preempting application could have changed any or all of those controls.
Since preemption does not deregister or destroy the ring buffer used by your path, you may resume usage of that same buffer, provided that all the path's controls are returned to the same values they had before the preemption (especially VL_SIZE and VL_PACKING). However, you might want to be doubly sure that the ring buffer is empty before restarting the transfer with a call to vlBeginTransfer().
If the call to vlSetupPaths() to regain access to the path's data stream fails (returns a negative value), the path should remain in the same mode in which it was before the failed call to vlSetupPaths(). If your program hasn't changed the path since it was preempted, and if the call to vlSetupPaths() failed with vl error VLPathInUse, the path should still be in the mode in which it was placed by the original preemption, namely as if vlSetupPaths(..., VL_SHARE, VL_READ_ONLY) had been done on this path. The path should continue to behave exactly as when it was preempted, and another VLStreamAvailable should be generated, if and when the path becomes available again.
A VL application that wishes to use the default input source node on a given device calls vlGetNode(vlServer, VL_SRC, VL_VIDEO, VL_ANY).
Each device's default input source node may be changed via a control. The Video Control Panel supports this, and is usually used to make this choice. When the default input source node on any VL video device is changed, (e.g. between a digital input source node and an analog input source node), the VL sends a VLDefaultSource event to all programs that have selected this event, regardless of whether they are using the device whose default input changed, or another VL device.
Each video source node may serve multiple jacks. The choice of active input jack on a given source node is done with some VL controls, VL_FORMAT or VL_MUXSWITCH, as described in Choosing an Input Jack. A change in input jack between jacks connected to the same video source node usually results in a VLControlChanged event, not a VLDefaultSource event.
If you wish your application to track the default input node, you must manually tear down and rebuild your video path each time you receive a VLDefaultSource event, like this:
While the path's stream usage is in VL_READ_ONLY mode, a VLStreamAvailable event should be generated when the data stream for the selected path becomes available. That is, a program should be able to put itself into a "voluntarily preempted" mode by putting the path's stream usage is in VL_READ_ONLY mode. Whether this actually works or not depends on the device, and on the OS release. It has worked on ev1 at one time. sirius does not support putting a path into VL_READ_ONLY mode. sirius also does not support preemption.
An application should be able to transition the stream usage of a path from any one to any other of the four modes (VL_SHARE, VL_READ_ONLY, VL_LOCK, VL_DONE_USING) as many times as it wishes. VL_DONE_USING is not the "mode of no return". The principal difference between VL_READ_ONLY and VL_DONE_USING seems to be the receipt of VLStreamAvailable events in the VL_READ_ONLY mode.
Since sirius doesn't support VL_READ_ONLY, an application cannot use VL_READ_ONLY to put itself into a mode where it will be notified when another device has finished with the path. A sirius app has no choice but to go to VL_DONE_USING mode when relenquishing the path, and to use some external or manual means to know when to attempt to reaquire the path.
Support This Site | This hobby site is supported by readers like you. To guarantee future updates, please support the site in one of these ways: |
![]() | Use your credit card or PayPal to donate in support of the site. |
![]() | Use this link to Amazon—you pay the same, I get 4%. |
![]() | Learn Thai with my Talking Thai-English-Thai Dictionary app: iOS, Android, Windows. |
![]() | Experience Thailand richly with my Talking Thai-English-Thai Phrasebook app. |
![]() | Visit China easily with my Talking Chinese-English-Chinese Phrasebook app. |
![]() | I co-authored this bilingual cultural guide to Thai-Western romantic relationships. |
Copyright | All text and images copyright 1999-2023 Chris Pirazzi unless otherwise indicated. |