Chapter 2. Programming DIVO

The DIVO board supports the Video Library (VL) and the Audio Library (AL) programming APIs. The APIs are described in the Digital Media Programming Guide (007-1799-060 or later; hereafter referred to as the DMPG).

This chapter explains

VL Basics for DIVO

To build programs that run under VL, you must

  • install the dmedia_dev and dmedia_eoe options

  • link with libvl

  • include dmedia/vl.h and dmedia/vl_DIVO.h for device-dependent functionality

The client library for VL is /usr/lib32/libvl.so. The header files for the VL are in /usr/include/dmedia; the main file is vl.h. This file contains the main definition of the VL API and controls that are common across all hardware. Several useful digital media programming examples are in /usr/share/src/dmedia/video.


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

For more information on the Video Library and the API usage, see the latest version of the DMPG.

This section explains

  • VL concepts

  • VL object classes

  • VL nodes for DIVO

  • VL data transfer functions

VL Concepts

The Video Library defines a basic set of primitives and mechanisms to specify interconnections and controls to achieve the desired setup. The two central concepts for VL are

  • path: an abstraction for a way of moving data around

  • node: an endpoint of the path

The basic nodes are a source (such as a VTR) and a drain (such as memory). Figure 2-1 diagrams the simplest VL path, with one of each of these two nodes.

Figure 2-1. Simple VL Path


The two other types of nodes besides source and drain are device node and internal node. DIVO does not support any internal nodes.

VL Object Classes

The VL recognizes five classes of objects:

  • devices, each including sets of nodes

  • nodes: sources, drains, and internal nodes (as discussed in the preceding section)

  • paths, connecting sources and drains (as discussed in the preceding section)

  • buffers, for sending and receiving field/frame data to and from host memory

    DIVO requires the use of DMbuffers (digital media buffers) and not the original ring buffer mechanisms (VL buffers) used with earlier Silicon Graphics video options. The new buffering scheme is much more flexible and versatile than the older VL buffer-based scheme. See Chapter 5 of the DMPG.

    As explained earlier, buffers are DMbuffers, an abstraction of main memory to allow efficient and API-independent interchange of data between the different digital media libraries. For example, video fields can be captured into DMbuffers via VL and then displayed in graphics using OpenGL. They can also be passed between two processes without the data having to be copied explicitly. Refer to Chapter 5, “Digital Media Buffers,” in the DMPG for details.

  • events, for monitoring video I/O status

  • controls, or parameters that modify how data flows through nodes; for example:

    • video device parameters, such as blanking width, gamma value, horizontal phase, sync source

    • video data parameters such as packing, size, and color space

VL controls fall into two categories:

  • device-global or device-independent (prefix VL_), which can be used by several Silicon Graphics video products

    For details of the device-independent controls, refer to the DMPG.

  • device-dependent (prefix VL_DIVO_), specific to a particular video device, in this case, DIVO

Both types of VL controls are explained in this chapter with respect to their usage with DIVO.

VL Nodes for DIVO

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

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

In this prototype, variables are as follows:

VLNode 

Handle for the node, used when setting controls or setting up paths.

VLNode 

Names the server (as returned by vlOpenVideo()).

VLNode 

Specifies the type of node:

  • VL_SRC: source, such as a digital tapedeck connected to a DIVO in port

  • VL_DRN: drain, such as system memory

  • VL_DEVICE: DIVO global control, such as trigger, GPI, sync, or default source; Table 2-1 summarizes the values for this type


    Note: If you are using VL_DEVICE, the VLNode (see below) should be set to 0.


VLNode 

Specifies the kind of node.

If VLNode is VL_SRC, VLNode values can be

  • VL_VIDEO: connection to a video device equipment; for example, a video tapedeck or camera

    If the VLNode is VL_SRC, the value is DIVO_SRC_DIGITAL_VIDEO (source node).

  • VL_MEM: workstation memory

If VLNode is VLNode, kind values can be

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

    If the type is VL_DRN, the value is DIVO_DRN_DIGITAL_VIDEO.

  • VL_MEM: workstation memory

VLNode 

Number of the node in cases of two or more identical nodes, such as two video source nodes. The default value for all kinds is 0.

VL_ANY can also used as a value for number to reference the first available node of the specified VLNode and VLNode.

In general, a path on DIVO has a memory node and a video node. The following fragment creates a digital video input source node and a memory drain node, and creates the path.

VLServer svr;
VLPath path;
VLNode src;
VLNode drn;
VLControlValue timing,format, ctrlval;
src = vlGetNode(svr, VL_SRC, VL_VIDEO, VL_ANY);
drn = vlGetNode(svr, VL_DRN, VL_MEM, VL_ANY);
if((path = vlCreatePath(svr, VL_ANY, src, drn)) < 0){
     fprintf(stderr,”%s\n”,vlStrError(vlGetErrno()));
     exit(1);
}
vlSetupPaths(svr, (VLPathList)&path, 1, VL_SHARE, VL_SHARE);

The following fragment illustrates the use of VL_ANY as the default node kind; it allows a program to accept input from whatever setting is specified in the video control panel vcp.

src = vlGetNode(svr, VL_SRC, VL_VIDEO, VL_ANY);

To discover the source node—not required here, because DIVO has only one input, but good programming practice nevertheless—you would use the control VL_DEFAULT_SOURCE with vlGetControl() after getting the node handle the normal way. For example:

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

In the second line above, the last argument is a struct that gets the value.

The following fragment adds a memory drain node.

drn = vlGetNode(svr, VL_DRN, VL_MEM, VL_ANY); /*Get a memory drain node */
vlAddNode(svr, path, drn); /* Add node to the exisiting path */ 

After nodes are specified, you use (vlSetControl()) to specify parameters;

  • video nodes: video timing (for example, CCIR 525) and format (for example digital component)

  • memory nodes: timing, packing, and color space

Controls for each node are defined in “DIVO Controls” later in this chapter, and are summarized in Table 2-3.

VL Data Transfer Functions

This section summarizes VL syntax elements and data transfer categories, and gives the basic steps of creating an application.

VL 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()

For DIVO, VL data transfers always involve memory (video to memory, memory to video) and require setting up a DMbuffer pool.

In the VL programming model, the process of creating a VL application consists of these steps:

  1. opening a connection to the video daemon (vlOpenVideo())

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

  3. creating the path (vlCreatePath())

  4. optional step: adding more nodes to a path (vlAddNode())

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

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

  7. setting input and output parameters (controls) for the nodes on the path (vlSetControl()); video format and timing must be specified

  8. creating a dmBuffer pool to hold data for memory transfers (vlDMGetParams(), dmBufferSetPoolDefaults(), dmBufferCreatePool(), vlGetTransferSize())

  9. registering the buffer (vlDMPoolRegister(),vlDMPoolDeregister())

  10. starting the data transfer (vlBeginTransfer())

  11. getting the data (vlDMBufferGetValid(), vlDMBufferPutValid(), dmBufferAllocate(), dmBufferMapData(), dmBufferFree()) to manipulate frame data

  12. cleanup (vlEndTransfer(), vlDMPoolDeregister(), vlDestroyPath(), vlCloseVideo())

Compression Through the VL

Compression is handled via enhancements to the VL API; the DIVO board does not support the Compression Library API.

Compression in the VL is supported by adding compression-related controls on memory nodes. The control VL_COMPRESSION specifies the compression. Based on the compression type, additional controls specify compression-related parameters. Table 2-2 later in this chapter summarizes these controls.

DIVO can use Rice compression, a lossless entropy coding mechanism that provides an average compression of 2:1. In some cases, compression can add to the size of the data being transferred, but is limited to a maximum of 1% bloat. Tests at Silicon Graphics show that this compression mechanism can reduce data in ratios of 2:1 to 6:1.

DIVO Controls

To determine the available devices (that is, video options in the workstation, such as the DIVO board) and the nodes available on them, run vlinfo. To determine possible controls for each device, run

vlinfo -l


Note: VL controls specified as true with vlSetControl() are executed immediately. However, they are not guaranteed to happen at a specific time. For better precision on the execution of these controls, see “Specifying Execution Times,” later in this chapter.

To set controls for DIVO nodes, use vlSetControl(). The following example sets video format and timing on a node.

timing.intVal = VL_TIMING_525_CCIR601;
format.intVal = VL_FORMAT_RGB;

if (vlSetControl(svr, path, drn, VL_TIMING, &timing) <0)
{
     vlPerror(“VlSetControl:TIMING”);
     exit(1);
}
if (vlSetControl(svr, path, drn, VL_FORMAT, &format) <0)
{
     vlPerror(“VlSetControl:FORMAT”);
     exit(1);
 }

For details on vlSetControl() and vlGetControl(), see the latest version of the DMPG.

Tables in this section summarize

  • device-global controls for DIVO

  • controls for DIVO nodes

  • control values and uses

The online device-global control for DIVO is VL_DEFAULT_SOURCE (value DIVO_SRC_DIGITAL_VIDEO), which determines the source node selected by VL when VL_ANY has been specified as the source node. DIVO has only one video source.

Table 2-1 summarizes supported node controls for DIVO.

Table 2-1. DIVO Node Controls

Control

Video Source

Memory Source

Video Drain

Memory Drain

VL_ASPECT (read only)

 

X

 

X

VL_CAP_TYPE

 

X

 

X

VL_COLORSPACE

 

X

 

X

VL_COMPRESSION

 

X

 

X

VL_DIVO_EXTRACT_VITC

X

 

 

 

VL_DIVO_INSERT_VITC

 

 

X

 

VL_DIVO_LOOPBACK

X

 

 

 

VL_DIVO_RASTER_MODE

 

X

 

X

VL_FIELD_DOMINANCE

X

 

X

 

VL_FORMAT

X

 

X

 

VL_GPI_OUT_MODE

X

 

X

 

VL_GPI_STATE

X

 

X

 

VL_OFFSET (read-only on video nodes)

X

X

X

X

VL_PACKING

 

X

 

X

VL_RICE_COMP_DITHER

 

X

 

X

VL_RICE_COMP_PRECISION

 

X

 

X

VL_RICE_COMP_SAMPLING

 

X

 

X

VL_SIZE (read-only on video nodes)

X

X

X

X

VL_SYNC

 

 

X

 

VL_SYNC_SOURCE

 

 

X

 

VL_TIMING

X

X

X

X

VL_TRANSFER_TRIGGER

X

 

X

 

VL_ZOOM (read-only)

X

X

X

X

Table 2-2 summarizes the values and uses of controls for DIVO.

Table 2-2. Controls for DIVO

Control

Values or Range

Use

VL_ASPECT

Aspect (read-only).

Reads aspect ratio.

VL_CAP_TYPE

Memory nodes:

VL_CAPTURE_FIELDS
VL_CAPTURE_INTERLEAVED
VL_CAPTURE_NONINTERLEAVED

Selects type of frame(s) or field(s) to capture.

VL_COLORSPACE

VL_COLORSPACE_RGB (full-range RGB)
VL_COLORSPACE_CCIR601(compressed range YUV)
VL_COLORSPACE_RP175 (compressed range RGB)
VL_COLORSPACE_YUV (full-range YUV)

Specifies color space of video data in memory.

VL_COMPRESSION

VL_COMPRESSION_NONE
VL_COMPRESSION_RICE
VL_COMPRESSION_JPEG
VL_COMPRESSION_MPEG2
VL_COMPRESSION_DVCPRO

Specifies compression option for video.
See vl.h for information on compression-specific controls. For example, to access Rice entropy coding, use VL_COMPRESSION_RICE as the compression control for the memory node.

VL_DIVO_EXTRACT_VITC

VL_DIVO_EXTRACT_NONE
VL_DIVO_EXTRACT_LINK_A
VL_DIVO_EXTRACT_LINK_B

Specifies the link from which to extract VITC.

VL_DIVO_INSERT_VITC

VL_DIVO_INSERT_NONE
VL_DIVO_INSERT_BOTH_LINKS

Specifies whether to insert VITC or not.

VL_DIVO_LOOPBACK

VL_DIVO_LOOPBACK_ON
VL_DIVO_LOOPBACK_OFF

Specifies if the video source on input should be from the output pipe.

VL_DIVO_RASTER_MODE

VL_DIVO_VIDEO

VL_DIVO_DATA

Grabs video specified by the VL_SIZE and VL_OFFSET.

Grabs or puts the full raster; used for SDDI or CSDI interfaces.

VL_FIELD_DOMINANCE

VL_F1_IS_DOMINANT
VL_F2_IS_DOMINANT

Note: Frames that are output are deinterlaced differently depending on the choice of output field dominance. Deinterlacing is specified in the application.

Identifies frame boundaries in a field sequence; see “Setting Field Dominance.”

VL_FORMAT


VL_FORMAT_DIGITAL_COMPONENT_SERIAL
VL_FORMAT_DIGITAL_COMPONENT_DUAL_ SERIAL

Sets video format in or out:
Serial 4:2:2:4
Serial 4:4:4:4

VL_GPI_OUT_MODE





Conditions:
VL_GPI_OUT_XFER_START
VL_GPI_OUT_XFER_STOP

Specifies when the GPI_OUT line is asserted, to control downstream devices in a studio environment. For more information, see “VL Support for the General-Purpose Interface (GPI).”
Asserts GPI_OUT at BeginTransfer
Asserts GPI_OUT at EndTransfer

VL_GPI_STATE

State:
VL_GPI_CLEAR
VL_GPI_OFF
VL_GPI_ON
VL_GPI_PULSE (transition for one field time)

Sets/Gets the state of output_gpi lines. For more information, see “VL Support for the General-Purpose Interface (GPI).”

VL_OFFSET

Any position within the video raster.

Sets the position within the video raster to stuff bits.

VL_PACKING

Supported packings; see Appendix B, “Pixel Packings and Color Spaces,”for information

Sets packing format for memory source or drain node.

VL_RICE_COMP_DITHER

VL_RICE_DITHER_OFF
VL_RICE_DITHER_ON

Turns Rice dithering on or off.

VL_RICE_COMP_PRECISION

VL_RICE_COMPRESSION_8
VL_RICE_COMPRESSION_10
VL_RICE_COMPRESSION_12
VL_RICE_COMPRESSION_13

Specifies the component size.

VL_RICE_COMP_SAMPLING

VL_RICE_COMPRESSION_422
VL_RICE_COMPRESSION_4224
VL_RICE_COMPRESSION_444
VL_RICE_COMPRESSION_4444

Specifies the sampling resolution.

VL_SIZE

Any size of the raster.

Size plus offset or origin should not exceed the raster dimensions.

VL_SYNC

VL_SYNC_INTERNAL
VL_SYNC_GENLOCK

Sets sync mode for analog video source or drain; on source, this is set to VL_SYNC_GENLOCK.

VL_SYNC_SOURCE

VL_DIVO_SYNC_STANDALONE
VL_DIVO_SYNC_HOUSE
VL_DIVO_SYNC_DIGITAL_INPUT
VL_DIVO_SYNC_DBOARD

Selects the genlock source: VL_DIVO_SYNC_DBOARD is used when the compressed stream provides a sync source.

VL_TIMING


VL_TIMING_525_CCIR601
VL_TIMING_625_CCIR601

Sets or gets video timing:
13.50 MHz, 720 x 486
13.50 MHz, 720 x 576

VL_TRANSFER_TRIGGER

VL_TRIGGER_NONE
VL_TRIGGER_GPI
VL_TRIGGER_VITC
VL_TRIGGER_MSC

Specifies the conditions under which transfers begin on a path (video nodes only); see “Using VL_TRANSFER_TRIGGER” in this chapter.

VL_ZOOM

Zoom factor (read-only)

 

Reads zoom factor of video stream.


Setting Field Dominance

Field dominance identifies the frame boundaries in a field sequence, that is, it specifies which pair of fields in a field sequence constitute a frame. The control VL_FIELD_DOMINANCE allows you to specify whether an edit occurs on the nominal video field boundary (field 1) or on the intervening field boundary (field 2)).

  • “F1 dominant”: the edit occurs on the nominal video field boundary

  • “F2 dominant”: the edit occurs on the intervening field boundary

Figure 2-2 shows fields as defined for NTSC and PAL.


Note: In digital formats and other input modes, half lines become full lines.

Figure 2-2. Fields and Frames for NTSC and PAL


Users typically want to edit on Field 1 boundaries, where Field 1 is defined as the first field in the video standard's two-field output sequence. 525 standards send the second (whole) raster line out to begin the first field, and the first (half) raster line out to begin the second field; 625 standards send the first (half) raster line out to begin the first field, and the second (whole) raster line to begin the second field.

Some users may want to edit on F2 boundaries, which fall on the field in between the video standard's frame boundary. To do so, use this control, then program your deck to select F2 edits.

NTSC users might need to vary their field dominance choice, depending on the origin of the input material they are to edit.


Note: To output a set of frames, they must be deinterlaced into fields differently, depending on the choice of output field dominance. For example, when F1 dominance is selected, the field with the topmost line must be the first field to be transferred; when F2 dominance is selected, the field with the topmost line must be the second field to be transferred. Deinterlacing must be specified in the application; the following code fragment contains an example of how to consult the field dominance control to determine deinterleave order.


/*
* Set the memory node's timing based upon the video drain's timing,
 * which has been set up by the daemon from the defaults file, or by
 * the user via vcp.
 *
 * When we get around to reading image files, we'll check the file
 * size against the size reported by the VL for this node: if the file
 * size does not match the format's, we'll punt.
 */

if (vlGetControl(svr, MEMtoVIDPath, drn, VL_TIMING, &drainTiming) < 0) {
	    vlPerror(“GetControl(VL_TIMING) on video drain failed”);
    exit(1);
}
if (vlSetControl(svr, MEMtoVIDPath, src, VL_TIMING, &drainTiming) < 0) {
    vlPerror(“SetControl(VL_TIMING) on memory source failed”);
    exit(1);
}
/*
 * Read the video drains's field dominance control setting and timing,
 * then set a variable to indicate which field has the first line, so 
 * readimage() will know how to deinterleave frames to fields.
 */
if (vlGetControl(svr, MEMtoVIDPath, drn,
    VL_FIELD_DOMINANCE, &dominance) < 0) {
    vlPerror(“GetControl(VL_FIELD_DOMINANCE) on video drain failed”);
    exit(1);
}

is_525 = (drainTiming.intVal == VL_TIMING_525_CCIR601));

switch (dominance.intVal) {
    case VL_F1_IS_DOMINANT:
        if (is_525) {
        F1_is_first = 0;
        } else {
        F1_is_first = 1;
        }
        break;
    case VL_F2_IS_DOMINANT:
        if (is_525) {
        F1_is_first = 1;
        } else {
        F1_is_first = 0;
        }
        break;
    }

/*
 * Read the video drain's field dominance control setting and set a
 * variable to indicate which field has the first line.
*/
if (vlGetControl(svr, MEMtoVIDPath, drn,
    VL_FIELD_DOMINANCE, &val) < 0) {
    vlPerror(“GetControl(VL_FIELD_DOMINANCE) on video drain failed”);
    exit(1);
}

switch (val.intVal) {
    case VL_F1_IS_DOMINANT:
        F1_is_first = 1;
        break;
    case VL_F2_IS_DOMINANT:
        F1_is_first = 0;
        break;
    }

To assemble fields to frames, the application must consult the field dominance control in order to determine the interleave order. The following code fragment contains an example of how to consult the field dominance control to determine interleave order.

/*
 * Set the memory node's timing based upon the video source's timing,
 * which has been set up by the daemon from the defaults file, or by
 * the user via vcp.
 */
if (vlGetControl(svr, path, src, VL_TIMING, &timing) < 0) {
    vlPerror(“GetControl Failed”);
    exit(1);
}
if (vlSetControl(svr, path, drn, VL_TIMING, &timing) < 0) {
    vlPerror(“SetControl Failed”);
    exit(1);
}
/*
 * Read the video source's field dominance control setting and timing,
 * then set a variable to indicate which field has the first line.
*/
if (vlGetControl(svr, path, src,
    VL_FIELD_DOMINANCE, &dominance) < 0) {
    vlPerror(“GetControl(VL_FIELD_DOMINANCE) on video source failed”);
    exit(1);
}

is_525 = (timing.intVal == VL_TIMING_525_CCIR601));

switch (dominance.intVal) {
    case VL_F1_IS_DOMINANT:
        if (is_525) {
        F1_is_first = 0;
        } else {
        F1_is_first = 1;
        }
        break;
    case VL_F2_IS_DOMINANT:
        if (is_525) {
        F1_is_first = 1;
        } else {
        F1_is_first = 0;
        }
        break;
    }

VL Support for the General-Purpose Interface (GPI)

The VL API supports the GPI as a device-independent interface. It supports GPI triggers in three vlSetControl() interfaces. The union VLControlValue has been extended to support the controls

  • transfer_trigger

  • gpi_out, for output triggering

  • gpi_state, for explicitly setting and querying the GPI lines


Note: Use the VL_TRANSFER_TRIGGER, supported on video nodes, to set up triggering for beginning the transfers on a path. For more information, see “Using VL_TRANSFER_TRIGGER,” later in this chapter. See Appendix A, “DIVO I/O Panel Connector Specifications,” for hardware information on the GPI interface.


Using VL_GPI_OUT_MODE

Use VL_GPI_OUT_MODE to program the gpi_out line. Three conditions are supported for asserting the GPI line: transfer_start, transfer_stop, and msc. You can have multiple trigger conditions outstanding.

The following code segment illustrates a setup for gpi_out line 1 to toggle at the beginning and end of transfer.

VLControlValue val;

                          /* make sure the GPI line is high */
val.gpi_state.gpi   = VL_GPI_OUT;
val.gpi_state.instance = <which GPI line>;
val.gpi_state.state =  VL_GPI_OFF;   
vlSetControl(svr,path,VL_GPI_STATE,&val);

                          /* transfer start */
val.gpi_out.condition = VL_GPI_OUT_XFER_START;
val.gpi_out.instance  = <which GPI output line >;
val.gpi_out.state     = VL_GPI_ON;

vlSetControl(svr,path,VL_GPI_OUT_MODE,&val);

                          /* transfer stop */
val.gpi_out.condition = VL_GPI_OUT_XFER_STOP;
val.gpi_out.instance  = <which GPI output line >;
val.gpi_out.state     = VL_GPI_OFF;

vlSetControl(svr,path,VL_GPI_OUT_MODE,&val);

To clear all outstanding trigger controls on a particular line, use the gpi_state control with the clear flag.

Using VL_GPI_STATE

Use VL_GPI_STATE to query the state of the input GPI lines and to set or get the state of output GPI lines. The states are ON, OFF, PULSE (transition for one field time), and CLEAR.

The following code fragment clears all output triggers on the specified line.

VLControlValue val; 

val.gpi_state.gpi   = VL_GPI_OUT;
val.gpi_state.instance = <which GPI line>;
val.gpi_state.state =  VL_GPI_CLEAR;

vlSetControl(svr,path,VL_GPI_STATE,&val);

To get the GPI state on an input line, use

val.gpi_state.gpi = VL.GPI.IN;
val.gpi_state.instance = <which GPI line>;
vlGetControl (svr, path, VL_GPI_STATE, &val);

DIVO Events and Triggering

The VL provides several ways of handling data stream events, such as completion or failure of data transfer, vertical retrace event, loss of the path to another client, lack of detectable sync, or dropped fields or frames. The method you use depends on the kind of application you are writing:

  • For a strictly VL application, use

    • vlSelectEvents() to choose the events to which you want the application to respond

    • vlCallback() to specify the function called when the event occurs

    • your own event loop or a main loop (vlMainLoop()) to dispatch the events

  • For an application that also accesses another program or device driver, or if you are adding video capability to an existing X or OpenGL application, set up an event loop in the main part of the application and use the IRIX file descriptor (FD) of the event(s) you want to add.

For more information on these functions, see Chapter 4 in the Digital Media Programming Guide.

Table 2-3 summarizes events for DIVO. For DIVO, this table supersedes the table of events in Chapter 14, “VL Event Handling,” in the DMPG; DIVO supports only the events listed in Table 2-3.

Table 2-3. DIVO Events

Event

Use

VLSyncLost

Sync is not detected

VLStreamStarted

Stream started delivery

VLStreamStopped

Stream stopped delivery

VLSequenceLost

A field/frame was dropped

VLControlChanged

A control on the path has changed

VLTransferComplete

A field/frame transfer has completed

VLTransferFailed

A transfer has failed and DMA is aborted

VLFrameVerticalRetrace

Vertical retrace event for a frame

VLDeviceEvent

A device-specific event

VLTransferError

A transfer error was discovered; field may be invalid


Specifying Execution Times

Controls executed with vlSetControl() have no guarantees as to when they are executed once transfers are in progress because of the asynchronous nature of the implementation. However, in certain situations, it is useful to be able to specify when controls on a path are executed, for example, to play out video clips with different packings or color-space formats without having to stop transfers while a memory-to-video operation is in progress. You can specify execution times by

Using vlSetControlInLine() to Set In-Line Controls

In-line controls specify control changes to happen between buffers. For example, if you want to play out two video clips which have different packing formats in memory, the application would set up the path, queue the buffers from the first clip, setup in-line controls to match the next clip, and queue the buffers from the second clip. The syntax for usage is

int vlSetControlInLine(VLServer svr, VLPath path, VLNode node, 
     VLNode refnode, VLControlType control, VLControlValue *controlVal)

In this syntax, refnode is the reference node, identifying a unique connection in a path with more than two nodes.

In-line controls are generally applied on memory nodes, where the memory node is the source node. Control changes are queued to the hardware along with the buffers and are executed in order. To change packing control in-line, for example, use

Controlval.intval = VL_PACKING_444_12;
vlSetControlInLine(svr,path,vlMem, vlMem, VL_PACKING, &ControlVal;

Using vlSetControlTrigger() to Set Trigger Controls

Trigger controls specify control changes at a specified trigger point. This mechanism is useful for triggering actions associated with GPI, MSC, or VITC. The syntax is

int vlSetControlTrigger(VLServer svr, VLPath path, VLNode node,     
     VLTriggerType trigger, VLTriggerData *triggerdata, 
     VLControlType control, VLControlValue *contrlVal) 

VLTriggerType is VL_TRIGGER_MSC, VL_TRIGGER_GPI, or VL_TRIGGER_VITC.

VLTriggerData is defined as follows:

typedef union {
    VLNode refnode; /* trigger defined with reference to this node 
         - MSC */
} VLTriggerParam;

The refnode, along with node, identifies a unique connection in the path where more then two nodes constitute a path.

typedef union {
    stamp_t msc;        /* msc trigger - MSC */
    uint32_t instance;  /* Which trigger - GPI */
    DMtimecode vitc;    /* vitc - VITC */
} VLTriggerVal;   
typedef struct {
    VLTriggerParam param;
    VLTriggerVal val;
} VLTriggerData;

Trigger controls are generally applied on video nodes. For example, you can use this control to change VL_FORMAT at a trigger point from single-link to dual-link in a switched studio environment, as in the following fragment.

VLNode video_node, mem_node;
VLTriggerData triggerData;
VLControlValue contrlVal;

triggerData.param.refnode = mem_node; /* identifies the connection
       within the path */
triggerData.vl.msc = <which gpi> /* which gpi input line to trigger 
       on */

contrlVal.intVal = VL_FORMAT_DIGITAL_COMPONENT_DUAL_SERIAL
vlSetControlTrigger (svr, path, video_node, VL_TRIGER_GPI,
       &triggerData, VL_FORMAT, &contrlVal);

Using VL_TRANSFER_TRIGGER

The VL_TRANSFER_TRIGGER control specifies the conditions under which transfers begin on a path. The trigger points could be based on the MSC of the incoming or outgoing field, external GPI triggers, or the time code of the field. Syntax for usage is as follows:

typedef struct {
  int triggerType;  /*VL_TRIGGER_GPI, VL_TRIGGER_VITC,VL_TRIGGER_MSC */   
  VLTriggerVal value;
} VLTrigger;
/* Trigger-specific data */
typedef union {
    stamp_t msc;        /* msc trigger - MSC */
    uint32_t instance;  /* Which trigger - GPI */
    DMtimecode vitc;    /* vitc - VITC */
} VLTriggerVal;   
{
...
VLTrigger xfer_trigger;
} VLControlValue

vlSetControl(svr, path, node, VL_TRANSFER_TRIGGER, VLControlValue *);

This control is valid only on video nodes.

The following code illustrates a GPI-based trigger transfer setup.

VLControlValue val;

val.xfer_trigger.triggerType = VL_TRIGGER_GPI;
val.xfer_trigger.value.instance = <which GPI input line>
vlSetControl(svr,path,VL_TRANSFER_TRIGGER,&val);

Reporting

The DMediaInfo structure has been enhanced to report the Unadjusted System Time (UST) and VITC information.

DIVO makes use of the error events noted in Chapter 4 of the DMPG, plus VLTransferErrorEvent, which reports nonfatal video transfer errors, including EDH errors. The VLTransferComplete and VLSequenceLost events also report the Media Stream Count (MSC) of the field transferred or failed.

AL Basics

The DIVO board supports 16 channels of audio and is compliant with the SMPTE 272M standard. Access to the audio is through the Audio Library (AL) interfaces specified in the DMPG.