Chapter 2. Setting Up Your VL Application

Used in conjunction with your OCTANE Personal Video option, Video Library (VL) calls let you capture any part of the screen display and scale it down, output computer-generated graphics to videotape or the O2Cam digital camera, and output the input video source to the graphics monitor, to a video device such as a VCR, or both.

This chapter explains the first steps for creating video programs for OCTANE Personal Video:

The VL Programming Model

Syntax elements are as follows:

  • VL types and constants begin with uppercase VL; for example, VLServer

  • VL functions begin with lowercase vl; for example, vlOpenVideo()

Data transfers fall into two categories:

  • transfers involving memory (video to memory, memory to video), which require setting up a buffer

  • transfers not involving memory (such as video to screen and graphics to video), which do not require a buffer

For the two categories of data transfer, based on the VL programming model, the process of creating a VL application consists of these steps:

  1. Open a connection to the video daemon (vlOpenVideo()); if necessary, determine which device the application will use (vlGetDevice(), vlGetDeviceList()).

  2. Specify nodes on the data path (vlGetNode()).

  3. Create the path (vlCreatePath()).

  4. (Optional step) Add more connections to a path (vlAddNode()).

  5. Set up the hardware for the path (vlSetupPaths()).

  6. Specify path-related events to be captured (vlSelectEvents()).

  7. Set input and output parameters (controls) for the nodes on the path (vlSetControl()).

  8. For transfers involving memory, create a VL buffer to hold data for memory transfers (vlGetTransferSize(), dmBufferCreatePool() or vlCreateBuffer()).

  9. For transfers involving memory, register the buffer (vlRegisterBuffer()) or (video-to-memory only) vlDMBufferPoolRegister()

  10. Start the data transfer (vlBeginTransfer()).

  11. For transfers involving memory, get the data and manipulate it (DMbuffers: vlDMBufferGetValid(), vlGetActiveRegion(), dmBufferFree(); VL buffers: vlGetNextValid(), vlGetLatestValid(), vlGetActiveRegion(), vlPutFree()).

  12. Clean up (vlEndTransfer(), vlDeregisterBuffer(), vlDestroyPath(), dmBuffer() or vlDestroyBuffer(), vlCloseVideo()).

Performing Preliminary Steps

To build programs that run under VL, you must

  • install the dmedia_dev option

  • link with

  • include vl.h and dev_evo.h

The client library is /usr/lib/ The header files for the VL are in /usr/include/dmedia. The header file for the VL, vl.h, contains the main definition of the VL API and controls. The header file for OCTANE Personal Video is /usr/include/dmedia/vl_evo.h (linked to /usr/include/vl/dev_evo.h).

Note: When building a VL-based program, you must add -lvl to the linking command.

Opening a Connection to the Video Daemon

The first thing a VL application must do is open the device with vlOpenVideo(). Its function prototype is

VLServer vlOpenVideo(const char *sName) 

where sName is the name of the server to which to connect; set it to a NULL string for the local server. For example:

vlSvr = vlOpenVideo("")

Specifying Nodes on the Data Path

Use vlGetNode() to specify nodes; this call returns the node's handle. Its function prototype is

VLNode vlGetNode(VLServer vlSvr, int type, int kind, int number) 



is a handle for the node, used when setting controls or setting up paths


names the server (as returned by vlOpenVideo())


specifies the type of node:

  • VL_SRC: source

  • VL_DRN: drain

  • VL_DEVICE: device for device-global controls

    Note: If you are using VL_DEVICE, the kind should be set to 0.


specifies the kind of node:

  • VL_MEM: region of workstation memory

  • VL_SCREEN: workstation screen (source only)

  • VL_VIDEO: connection to a video device; for example, a video tape deck or O2Cam digital camera

Note: Appendix B, “OCTANE Personal Video Nodes and Their Controls,” gives full details of all OCTANE Personal Video nodes.


is the number of the node in cases of two or more identical nodes, such as three video source nodes

To discover which node the default is, use the control VL_DEFAULT_SOURCE after getting the node handle the normal way. The default video source is maintained by the VL. For example:

vlGetControl(vlSvr, path, VL_ANY, VL_DEFAULT_SOURCE, &ctrlval);
nodehandle = vlGetNode(vlSvr, VL_SRC, VL_VIDEO, ctrlval.intVal);

In the first line above, the last argument is a struct that retrieves the value. Corresponding to VL_DEFAULT_SOURCE, the control VL_DEFAULT_DRAIN gets the default VL_SRC node.

Creating and Setting Up the Data Path

Once nodes are specified, use VL calls to

  • create the path

  • get the device ID

  • add nodes (optional step)

  • set up the data path

  • specify the path-related events to be captured

Creating the Path

Use vlCreatePath() to create the data path. Its function prototype is

VLPath vlCreatePath(VLServer vlSvr, VLDev vlDev
    VLNode src, VLNode drn) 

This code fragment creates a path if the device is unknown:

if ((path = vlCreatePath(vlSvr, VL_ANY, src, drn)) < 0) {

This code fragment creates a path that uses a device specified by parsing a devlist:

if ((path = vlCreatePath(vlSvr, devlist[devicenum].dev, src,
    drn)) < 0) {

Note: If the path contains one or more invalid nodes, vlCreatePath() returns VLBadNode.

Getting the Device ID

If you specify VL_ANY as the device when you create the path, use vlGetDevice() to discover the device ID selected. Its function prototype is

VLDev vlGetDevice(VLServer vlSvr, VLPath path)

For example:

devicenum = vlGetDevice(vlSvr, path);
deviceName = devlist.devices[devicenum].name;
printf("Device is: %s/n", deviceName);

Adding a Node

For this optional step, use vlAddNode(). Its function prototype is

int vlAddNode(VLServer vlSvr, VLPath vlPath, VLNodeId node)



names the server to which the path is connected


is the path as defined with vlCreatePath()


is the node ID

This example fragment adds a video source node and a device node:

vlAddNode(vlSvr, vlPath, src_vid); 
vlAddNode(vlSvr, vlPath, dev_node); 

Setting Up the Data Path

Use vlSetupPaths() to set up the data path. Its function prototype is

int vlSetupPaths(VLServer vlSvr, VLPathList paths,
      u_int count, VLUsageType ctrlusage,
      VLUsageType streamusage) 



names the server to which the path is connected


specifies a list of paths you are setting up


specifies the number of paths in the path list


specifies usage for path controls:

  • VL_SHARE: other paths can set controls on this node; this control is the desired setting for other paths, including vcp, to work

    Note: When using VL_SHARE, pay attention to events. If another user has changed a control, a VLControlChanged event occurs.

  • VL_READ_ONLY: controls cannot be set, only read; for example, this control can be used to monitor controls

  • VL_LOCK: prevents other paths from setting controls on this path; controls cannot be used by another path

  • VL_DONE_USING: the resources are no longer required; the application releases this set of paths for other applications to acquire


specifies usage for the data:

  • VL_SHARE: transfers can be preempted by other users; paths contend for ownership

    Note: When using VL_SHARE, pay attention to events. If another user has taken over the node, a VLStreamPreempted event occurs.

  • VL_READ_ONLY: the path cannot perform transfers, but other resources are not locked; set this value to use the path for controls

  • VL_LOCK: prevents other paths that share data transfer resources with this path from transferring; existing paths that share resources with this path will be preempted

  • VL_DONE_USING: the resources are no longer required; the application releases this set of paths for other applications to acquire

This example fragment sets up a path with shared controls and a locked stream:

if (vlSetupPaths(vlSvr, (VLPathList)&path, 1, VL_SHARE,
    VL_LOCK) < 0)

Specifying the Path-Related Events to Be Captured

Use vlSelectEvents() to specify the events you want to receive. Its function prototype is

int vlSelectEvents(VLServer vlSvr, VLPath path, VLEventMask eventmask)



names the server to which the path is connected


specifies the data path.


specifies the event mask; Table 2-1 lists the possibilities

Table 2-1 lists and describes the VL event masks

Table 2-1. VL Event Masks




Stream is locked


Stream was grabbed by another path


Video routing on this path has been changed by another path


Time was already reached


Irregular or interrupted signal


Field or frame dropped


A control has changed


A control range has changed


Control of a node has been preempted, typically by another user setting VL_LOCK on a path that was previously set with VL_SHARE


Access is now available


Transfer of field or frame complete


Error; transfer terminated; perform cleanup at this point, including vlEndTransfer()


Vertical retrace event, even field


Vertical retrace event, odd field


Frame vertical retrace event


Device-specific event, such as a trigger


Default source changed


For example:

vlSelectEvents(vlSvr, path, VLTransferCompleteMask); 

Event masks can be Or'ed; for example:

vlSelectEvents(vlSvr, path, VLTransferCompleteMask |

For more details on VL event handling, see Chapter 7, “Event Handling.”