Chapter 2. Programming DIVO and DIVO-DVC

The DIVO and DIVO-DVC boards support 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 and DIVO-DVC

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/tools (such as capture/avcapture, capture/avplayback, and vlan/vlan).


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

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 

Simple VL Path 

DIVO/DIVO-DVC nodes are further discussed in “VL Nodes for DIVO and DIVO-DVC ”.

VL Syntax Elements

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

VL Object Classes

The VL recognizes these classes of objects:

  • devices, each including sets of nodes

  • nodes, which are 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 and DIVO-DVC require the use of DMbuffers (digital media buffers) and not the original ring buffer mechanisms (VL buffers) used with earlier SGI 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.

    DMbuffers, an abstraction of main memory, 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 Digital Media Programming Guide 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 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 SGI 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 and DIVO-DVC

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

VL Nodes for DIVO and DIVO-DVC

Use  vlGetNode() to specify nodes. This call returns the node's handle, which is used when setting controls or setting up paths. Its function prototype is:

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

In this prototype, variables are as follows:

svr 

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

type 

Specifies the type of node:

  • VL_SRC: source , such as a digital tapedeck connected to an input port


    Note: The DIVO and DIVO-DVC options have only one input.


  • VL_DRN: drain , such as system memory

  • VL_DEVICE: global control, such as a default source; Table 2-1 summarizes the values for this type


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


kind 

Specifies the kind of node:

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

  • VL_MEM: workstation memory

number 

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 specificated type and kind.

In general, a path on DIVO and DIVO-DVC 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;
                     /*Set up video source node */
VLControlValue timing,format, val; 
src = vlGetNode(svr, VL_SRC, VL_VIDEO, VL_ANY);
                     /*Set up memory drain node */
drn = vlGetNode(svr, VL_DRN, VL_MEM, VL_ANY); 
                     /* Create source-to-drain path */
if((path = vlCreatePath(svr, VL_ANY, src, drn)) < 0){ 
     fprintf(stderr,”%s\n”,vlStrError(vlGetErrno()));
     exit(1);
}
                     /* Set up path with shared src and drn node */
vlSetupPaths(svr, (VLPathList)&path, 1, VL_SHARE, VL_SHARE);

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

  • video nodes: video timing (drain only) and format (for example digital component)

  • memory nodes: timing, packing, and color space

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

VL Data Transfer Functions

This section summarizes VL data transfer categories, and gives the basic steps of creating an application. For DIVO and DIVO-DVC, VL data transfers always involve memory (video to memory, memory to video) and require setting up a DM buffer pool.

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

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

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

  3. Create the path (vlCreatePath()).

  4. Optional step: add more nodes to a path (vlAddNode()).

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

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

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

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

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

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

  11. Get the data (vlDMBufferGetValid(), vlDMBufferPutValid(), dmBufferAllocate(), dmBufferAllocateSize(), dmBufferGetPoolState(), dmBufferGetPoolFD(), dmBufferSetPoolSelectSize(), dmBufferMapData(), dmBufferFree()) to manipulate frame data.

  12. Handle data stream events (vlSelectEvents(), vlNextEvent(), vlPending()).

  13. Clean up (vlEndTransfer(), vlDMPoolDeregister(), vlDestroyPath(), vlCloseVideo()).


    Note: Error handling (vlPerror()) is accomplished throughout.


DIVO/DIVO-DVC Controls

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

vlinfo -l


Note: VL controls specified as true with vlSetControl() are executed immediately. However, it is not guaranteed that they execute at a specific time. For better precision on the execution of these controls, see “Setting Inline Controls ”.

To set controls for DIVO/DIVO-DVC 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/DIVO-DVC

  • controls for DIVO/DIVO-DVC nodes

  • control values and uses  

Table 2-1 summarizes supported node controls for the DIVO/DIVO-DVC option.

Table 2-1. DIVO/DIVO-DVC Node Controls

Control

Video Source

Memory Source

Video Drain

Memory Drain

VL_ASPECT

 

X (read-only)

 

X (read only)

VL_CAP_TYPE

 

X

 

X

VL_COLORSPACE

 

X

 

X

VL_COMPRESSION

 

X

 

X

VL_DIVO_CLOSED_CAPTION

X

 

X

 

VL_DIVO_FIELD_DISPLAY

X

 

X

 

VL_DIVO_LOOPBACK

X

 

 

 

VL_FIELD_DOMINANCE

X

 

X

 

VL_FORMAT

X

 

X

 

VL_GPI_OUT_MODE

X

 

X

 

VL_GPI_STATE

X

 

X

 

VL_OFFSET

X (read-only)

X

X (read-only)

X

VL_PACKING

 

X

 

X

VL_RICE_COMP_PRECISION

X

 

X

VL_RICE_COMP_SAMPLING

X

 

X

VL_SDTI_HEADER

 

X

 

X (read-only)

VL_SDTI_MODE

 

X

 

X

VL_SIZE

X (read-only)

X

X (read-only)

X

VL_SYNC

 

 

X

 

VL_SYNC_SOURCE

 

 

X

 

VL_TIMING

X (read-only)

X

X

X

VL_TRANSFER_TRIGGER

X

 

X

 

VL_ZOOM

X (read-only)

X (read-only)

X (read-only)

X (read-only)

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

Table 2-2. Controls for the DIVO and DIVO-DVC Option Boards

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_DV (DIVO-DVC only)
VL_COMPRESSION_DVCPRO (DIVO-DVC only)

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_CLOSED_CAPTION

VL_DIVO_CLOSED_CAPTION _ON

VL_DIVO_CLOSED_CAPTION _OFF

Specifies if closed-caption should be extracted from input or inserted into output.

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_FIELD_DISPLAY

VL_DIVO_FIELD_DISPLAY_F1F2
VL_DIVO_FIELD_DISPLAY_F2F1
VL_DIVO_FIELD_DISPLAY_F1F1
VL_DIVO_FIELD_DISPLAY_F2F2

Specifies output field display order. For example, to display only one field of a DVCPRO frame, use VL_DIVO_FIELD_DISPLAY_F1F1.

This control is supported only in DV/DVCPRO compression mode on the DIVO-DVC option board.

VL_FIELD_DOMINANCE

VL_F1_IS_DOMINANT
VL_F2_IS_DOMINANT

(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 or 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 C, “Pixel Packings and Color Spaces ”,

for information .

Sets packing format for memory source or drain node.

VL_RICE_COMP_PRECISION

VL_RICE_C OMPRESSION_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_SDTI_HEADER

stringVal

Sets or gets the SDTI header as an array of bytes (stringVal).

VL_SDTI_MODE

VL_SDTI_MODE_OFF
VL_SDTI_MODE_ON

Specifies if the memory node data should be processed as SDTI data.

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 source or drain; on source, this is set to VL_SYNC_GENLOCK.

VL_SYNC_SOURCE

VL_DIVO_SYNC_HOUSE
VL_DIVO_SYNC_DIGITAL_INPUT_LINK_A
VL_DIVO_SYNC_DIGITAL_INPUT_LINK_B
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.


Compression Through the VL

Compression is handled via enhancements to the VL API; the DIVO and DIVO-DVC boards do not support the Compression Library API.

For DIVO and DIVO-DVC, 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—Rice, DV (DIVO-DVC only), DVCPRO (DIVO-DVC only), DVCam (DIVO-DVC only), or none—additional controls specify compression-related parameters. Table 2-2 earlier in this chapter summarizes these controls.


Note: Compression for the DIVO-DVC option is different from compression for DIVO; see “DV and DVCPRO Compression for DIVO-DVC ”.


Rice Compression

The DIVO and DIVO-DVC option boards can use Rice compression, a lossless entropy coding mechanism that provides an average compression of 2:1 while retaining bit-accurate data. In some cases, compression can add to the size of the data being transferred, but is limited to a maximum of 1% increase. Tests at SGI show that this compression mechanism can reduce data in ratios of 2:1 to 6:1.

For encoding, specify the controls VL_COMPRESSION, VL_RICE_COMP_PRECISION, and VL_RICE_COMP_SAMPLING. For decoding, the control information is already embedded in the stream; you need specify only the data type, with the VL_COMPRESSION control. For best memory utilization with Rice compression, use variably sized buffers.

Refer to the source examples (divo_vidtomem.c for encoding and divo_memtovid.c for decoding) in the directory /usr/share/src/dmedia/video/DIVO.

DV and DVCPRO Compression for DIVO-DVC

The DIVO-DVC board is capable of additional types of encoding defined in the DV, DVCam, and DVCPRO standards. For DV/DVCam and DVCPRO encoding, specify the control VL_COMPRESSION with the VL_COMPRESSION_DV or VL_COMPRESSION_DVCPRO parameter, respectively. For decoding, the control information is already embedded in the stream; you need specify only the data type, with the VL_COMPRESSION control. DV/DVCam and DVCPRO compression mechanisms can reduce data in the ratio of 5:1.

For 525/60, frame size is 12,000 bytes; for 625/50, frame size is 144,000 bytes. You must specify VL_PACKING as VL_PACKING_DV, as illustrated by the following code fragment. 

{
   int GvlPacking;
   VLControlValue val;
   int GvlCspace;
   int GvlCapType;

VL_PACKING_242_8
VL_COLORSPACE_CCIR(0)

GvlCapType = VL_CAPTURE_INTERLEAVED;

   val.intVal = GvlPacking;
   if (vlSetControl(GvlSvr, GvlPath, GvlMemNode, VL_PACKING, &val) < 0)
   vl_error(“vlSetControl(VL_PACKING) on memory node”);
   if (vlGetControl(GvlSvr, GvlPath, GvlMemNode, VL_PACKING, &val) < 0)
   vl_error(“vlGetControl(VL_PACKING) on memory node”);
   if (val.intVal != GvlPacking)
   other_error(“can't set VL_PACKING on memory node”);

   val.intVal = GvlCspace;
   if (vlSetControl(GvlSvr, GvlPath, GvlMemNode, VL_COLORSPACE, &val) < 0)
   vl_error(“vlSetControl(VL_COLORSPACE) on memory node”);
   if (vlGetControl(GvlSvr, GvlPath, GvlMemNode, VL_COLORSPACE, &val) < 0)
   vl_error(“vlGetControl(VL_COLORSPACE) on memory node”);
   if (val.intVal != GvlCspace)
   other_error(“can't set VL_COLORSPACE on memory node”);

   val.intVal = GvlCapType;
   if (vlSetControl(GvlSvr, GvlPath, GvlMemNode, VL_CAP_TYPE, &val) < 0)
   vl_error(“vlSetControl(VL_CAP_TYPE) on memory node”);
   if (vlGetControl(GvlSvr, GvlPath, GvlMemNode, VL_CAP_TYPE, &val) < 0)
   vl_error(“vlGetControl(VL_CAP_TYPE) on memory node”);
   if (val.intVal != GvlCapType)
   other_error(“can't set VL_CAP_TYPE on memory node”);

}

Use the VL_DIVO_FIELD_DISPLAY control to specify output field display order. To display only one field of a DVCPRO frame, specify the field. In the following example, VL_DIVO_FIELD_DISPLAY_F2F2 is used:

/* display only field # 2 */
 field_display = VL_DIVO_FIELD_DISPLAY_F2F2;
 val.intVal = field_display;
 if (vlSetControl(GvlSvr, GvlPath, GvlVidNode, VL_DIVO_FIELD_DISPLAY, &val) <0)
     vl_error(“vlSetControl(VL_DIVO_FIELD_DISPLAY) on video node”);
 if (vlGetControl(GvlSvr, GvlPath, GvlVidNode, VL_DIVO_FIELD_DISPLAY, &val) <0)
     vl_error(“vlGetControl(VL_DIVO_FIELD_DISPLAY) on video node”);
 if (val.intVal != field_display)
     other_error(“can't set VL_DIVO_FIELD_DISPLAY on video node”);

Programming the DIVO/DIVO-DVC Board for SDTI

For the DIVO and DIVO-DVC options, SDTI with embedded DV is handled by means of features in the VL API and hardware support in the input and output pipes. The API includes the following SDTI features:

  • The 32-bit packing VL_PACKING_SDTI_DV specifies how the signal is stored in memory. The layout for this packing is diagrammed in “SDTI Packing ” in Appendix C in Appendix C, “Pixel Packings and Color Spaces ”.

  • The VL has two SDTI-related controls on memory nodes:

    • VL_SDTI_MODE enables or disables SDTI mode. When SDTI is enabled and the payload data type is DV, the start lines for each field are changed for 525 timing: start lines are F1=21, F2=284 instead of the default F1=21, F2=283. (For 625 timing, start lines are the same as the defaults, F1=23 and F2=336.)

    • VL_SDTI_HEADER sets or gets the SDTI header as an array of bytes; the data structure is explained in this section.

This section consists of the following:

SDTI Data Structure

For both DIVO and DIVO-DVC, the control VL_SDTI_HDR overlaps the string variable.
The SDTI header is defined in vl_divo.h as follows:

                /*  SDTI Header  */
typedef struct {
  u_char did;            /* data id identifier */
  u_char sdid;           /* sec. data id identifier */
  u_char dc;             /* data word count */
  u_char lnum[2];        /* linenumber0 and linenumber1 */
  u_char lnumcrc[2];     /* linenumber0 and linenumber1 crc */
  u_char aai_code;       /* appl identifier and code */
  u_char dst_addr[16];   /* destination address */
  u_char src_addr[16];   /* source address */
  u_char btype;          /* block type */
  u_char crcflag;        /* payload crc flag */
  u_char dextflag;       /* data extension flag */
  u_char reserved[4];    /* reserved words */
} 


void init_sdti_header_dv( sdti_hdr_t *  sdti_hdr, VLControlValue *val)
{
  int i;

  sdti_hdr->did           = 0x40; /* see smpte 305M spec */
  sdti_hdr->sdid          = 0x01;
  sdti_hdr->dc            = 0x2E;
  sdti_hdr->lnum[0]       = 0x00;
  sdti_hdr->lnum[1]       = 0x00;
  sdti_hdr->lnumcrc[0]    = 0x00;
  sdti_hdr->lnumcrc[1]    = 0x00;
  sdti_hdr->aai_code      = 0x01;

  for(i=0;i<16;i++) sdti_hdr->dst_addr[i] = 0; /* dst_addr[0] is msb */
  for(i=0;i<16;i++) sdti_hdr->src_addr[i] = 0; /* src_addr[0] is msb */

  sdti_hdr->btype         = DIVO_SDTI_BLOCK_TYPE_FIXED; /* fixed block, no ecc
*/
  sdti_hdr->crcflag       = 0x01;  /* insert CRC */
  sdti_hdr->dextflag      = 0x00;  /* no data extension packets */
  for(i=0;i<4;i++) sdti_hdr->reserved[i] = 0; /* set to zero */

  /* copy sdti header into control string variable */
  bcopy(sdti_hdr,val->stringVal,sizeof(sdti_hdr_t));

}

    /* Set the SDTI Header */
    if (vlSetControl(GvlSvr, GvlPath, GvlMemNode, VL_SDTI_HEADER, &val) < 0)
      vl_error(“vlSetControl(VL_SDTI_HEADER) on memory node”); 

Sending SDTI DV

To multiplex and send SDTI DV, follow these steps:

  1. Enable SDTI mode by setting the VL_SDTI_MODE control.

  2. Set the color space to VL_COLORSPACE_CCIR601.

  3. Set the packing to VL_PACKING_SDTI_DV.

  4. Initialize the SDTI header by setting the VL_SDTI_HEADER control. For an example, see init_sdti_header_dv in /usr/share/src/dmedia/video/DIVO/divo_memtovid.c 

  5. Set ysize to the active payload region.

  6. Multiplex DIF frames and send buffers. For an example, see init_sdti_header_dv in /usr/share/src/dmedia/video/DIVO/divo_memtovid.c


    Note: The Reed-Solomon error correction code (ECC) is not supported on DIVO or DIVO-DVC.


Receiving SDTI DV

To receive and demultiplex SDTI DV, follow these steps:

  1. Enable SDTI mode by setting the VL_SDTI_MODE control.

  2. Set the color space to VL_COLORSPACE_CCIR601.

  3. Set the packing to VL_PACKING_SDTI_DV.

  4. Set ysize to the active payload region.

  5. Receive field buffers and demultiplex DIF frames. For an example, see init_sdti_header_dv in /usr/share/src/dmedia/video/DIVO/divo_memtovid.c

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 F1) or on the intervening field boundary (Field 2, or F2).

  • F1 dominant: The edit occurs on the nominal video field boundary.

  • F2 dominant: The edit occurs on the intervening field boundary.

Whether a field is Field 1 or Field 2 is determined by the setting of bit 9, the F bit, in the XYZ word of the EAV and SAV sequences. The setting means the following:

  • For Field 1 (also called the odd field), the F bit is 0.

  • For Field 2 (also called the even field), the F bit is 1.

Figure 2-2 shows fields and frames as defined for digital 525-line and 625-line formats for the DIVO/DIVO-DVC option.[1] 

Figure 2-2. DIVO/DIVO-DVC 525-Line and 625-Line Frames and Fields

DIVO/DIVO-DVC 525-Line and 625-Line Frames and Fields

Editing is usually on Field 1 boundaries, where Field 1 is defined as the first field in the video standard's two-field output sequence. 525-line 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-line standards send the first (half) raster line out to begin the first field, and the second (whole) raster line to begin the second field.

However, 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.

If you use component 525-line format, you might need to vary the field dominance choice, depending on the origin of the input material they are to edit.

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.
 */

int is_525, F1_is_first;
VLControlValue drn timing, dominance;
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;
    } 

VL Support for the General-Purpose Interface ( GPI)

The DIVO and DIVO-DVC option boards have two GPI connectors, each associated with one of the serial digital video ports. Each port has two transmit and two receive channels, lines 0 and 1 in and out.

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

Using VL_GPI_OUT_MODE

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

Figure 2-3 diagrams the effect of VL_GPI_OUT_MODE values.

Figure 2-3. Output GPI (OFF Assumed to Be Low)

Output GPI (OFF Assumed to Be Low)


Note: In this section, OFF is assumed to be low. VL_CLEAR_GPI changes the state of the GPI signal to low.


The following pseudocode 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>;       /* integer */
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:

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);

Using VL_TRANSFER_TRIGGER

The VL_TRANSFER_TRIGGER control specifies the conditions under which transfers begin on a path based on external GPI triggers. This control is valid only on video nodes.

The following code illustrates an input GPI-based trigger transfer setup:

VLTransferDescriptor desc;
int num_images = 30;   	/* 1 second of video */
int trigger = TRUE;		/* enable trigger transfers */

if (trigger) {
   val.xfer_trigger.triggerType = VL_TRIGGER_GPI;
   val.xfer_trigger.value.instance = 1;     /* GPI line 1 */
   desc.trigger = VLDeviceEvent;
}
else {   /* reset for subsequent transfers */
    val.xfer_trigger.triggerType = VL_TRIGGER_NONE;
    desc.trigger = VLTriggerImmediate;
}

vlSetControl(svr, path, src, VL_TRANSFER_TRIGGER, &val);

desc.mode = VL_TRANSFER_MODE_DISCRETE;
desc.count = num_images;
desc.delay = 0;

vlBeginTransfer(svr, path, 1, &desc);


Note: The trigger type is a persistent device control setting and remains valid until reset. Thus the VL_TRANSFER_TRIGGER control must be set to VL_TRIGGER_NONE if subsequent transfers are of a nontrigger type.


VL Support for Vertical Interval Time Code ( VITC)

Over-the-wire electrical time-code signals are used as clocks by which one master device can drive the input or output of data by other slave devices. Each tick of the clock consists of a unique signal that represents a time code.

VITC time code is a standardized part of a 525- or 625-line video signal. The code itself occupies lines in the vertical blanking interval of each field of the video signal. Each VITC code word contains a time code, 32 user bits, an F1/F2 field indicator, and other useful information. People use the user bits to store information such as reel and shot number for indexing footage. Under certain circumstances, the original VITC recorded with footage can go along with that footage as it is edited, so that you can produce an edit list or track assets for a final prototype edit.

The DIVO and DIVO-DVC options always extract VITC information from the fields as they are captured and pass this information to the application as buffer information associated with the dmBuffer. To extract this information, call vlDMBufferGetVideoInfo(). In the structure returned, a valid bit (validinfo) indicates if the VITC is valid. Refer to the programming example divo_vitc.c in the directory /usr/share/src/dmedia/video/DIVO.

To insert VITC, fill the DMBufferVideoInfo* structure and call the function vlDMBufferSetVideoInfo().

To parse a VITC image out of a pixel buffer, you can use a VITC parser included in libdmedia (see dmVITC(3dm)); see /usr/share/src/dmedia/video/vitc.c for sample code.

DIVO/DIVO-DVC Events

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/DIVO-DVC. For these options, this table supersedes the table of events in Chapter 14, “VL Event Handling,” in the DMPG; DIVO and DIVO-DVC support only the events listed in Table 2-3.

Table 2-3. DIVO/DIVO-DVC 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

VLEvenVerticalRetrace

Vertical retrace event for an even field

VLOddVerticalRetrace

Vertical retrace event for an odd field

VLDeviceEvent

A device-specific event

VLTransferError

A transfer error was discovered; field may be invalid


Setting Inline Controls

Because of the asynchronous nature of the implementation, controls executed with vlSetControl() have no guarantees as to when they are executed once transfers are in progress. 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.

Inline controls specify control changes to happen between buffers. For example, if you want to play out two video clips that have different packing formats in memory, the application would set up the path, queue the buffers from the first clip, set up inline 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 *val)

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

Inline controls are generally applied on a memory node being used as the source node. Control changes are queued to the hardware along with the buffers and are executed in order. To change packing control inline, for example, use

VLNode mem;

mem = vlGetNode(svr, VL_SRC, VL_MEM, VL_ANY);
val.intval = VL_PACKING_444_12;
vlSetControlInLine(svr, path, mem, mem, VL_PACKING, &val);

Capturing Graphics to Video

To capture graphics to video, you can use OpenGL to read pixels into memory. However, the coordinate system differs between video and Open GL; under OpenGL, the origin is at the lower left corner and in video, origin is in the upper left corner. To adjust for this difference, the image must be inverted in memory before it is sent to the DIVO board for output.

Besides sending an image out to the DIVO board, you can use the GVO graphics option to get zero-latency transcoding to CCIR 601-2 digital video.

Reporting

The DMediaInfo structure reports the Unadjusted System Time (UST) and VITC information.

The DIVO and DIVO-DVC options make use of the error events noted in Chapter 4 of the DMPG, as well as VLTransferErrorEvent, which reports nonfatal video transfer errors, including error detection and handling (EDH) errors. The VLTransferComplete and VLSequenceLost events also report the Media Stream Count ( MSC) of the field or frame transferred or failed.



[1] The line numbers for the DIVO/DIVO-DVC option diverge slightly from those defined in SMPTE 259M.