Producing live video output from the IndigoVideo board is simple. The IndigoVideo board constantly encodes a portion of the screen to video unless output has been explicitly turned off. You can also use IndigoVideo to produce single-frame output. In single-frame output mode, both live input and live output are disabled.
In this chapter:
“Selecting the IndigoVideo Live Output Area” explains how to designate a portion of the screen to be output to video.
“Setting Output Parameters” explains how to set up the output configuration.
“Generating Single-frame Output” explains how to output video one frame at a time.
Select the portion of the screen to be output using the svOutputOffset() routine. This routine specifies the upper left corner of the output “window.” The broadcast standard parameter (SV_BROADCAST) determines the size of the output area—640 by 480 pixels for NTSC, 768 by 576 pixels for PAL. svOutputOffset() does not create an actual window, and the output area is not in any way delineated on the Indigo workstation monitor.
Example 19-1 demonstrates setting the location of the IndigoVideo output area.
Example 19-1. Setting the Location of the IndigoVideo Output Window
#include <stdio.h>
#include <stdlib.h>
#include <svideo.h>
/*
* Simple Output Window
* Change output location of NTSC video window
*/
main(int argc, char *argv[])
{
int xstart, ystart;
SVhandle V;
if (argc != 3) {
fprintf(stderr, "Usage: %s x_start y_start\n", argv[0]);
exit(1);
}
xstart = atoi(argv[1]);
ystart = atoi(argv[2]);
/* open video device */
if ((V = svOpenVideo()) == NULL) {
svPerror("open");
exit(1);
}
/* change location of output window */
svOutputOffset(V, xstart, ystart);
exit(0);
}
|
You can use this program to record the output of any graphics program to videotape.
To select an output window:
Use xwininfo(1) to get the location of the desired window on the screen by entering:
xwininfo |
Place the mouse cursor in the window that you want information about and click any of the mouse buttons. xwininfo displays information about the selected window, including the coordinates of its upper left corner:
xwininfo ==> Window id: 0x3400001 (Hubert) |
==> Absolute upper-left X: 14 ==> Absolute upper-left Y: 156 ... |
You can then use these coordinates as arguments to vout to place the output area over the selected window:
vout 14 156 |
To incorporate video output into a program, you can use the code fragment from Example 19-2 to place the upper left corner of the output area at the upper left corner of the current IRIS GL window.
Example 19-2. Aligning a Video Output Area with an IRIS GL Window
long x, y, xsize, ysize, screensize; SVhandle V; /* ... */ getorigin(&x, &y); getsize(&xsize, &ysize); screensize = getgdesc(GD_YPMAX); y = screensize - (y + ysize); svOutputOffset(V, x, y); |
Your program should recalculate the output offset whenever a “REDRAW” event is received so that the program relocates the output area whenever you move the window.
This section explains how to set parameters that affect live video output.
The SV_VIDEO_OUTPUT parameter can be used to turn live video output on and off. The default value for SV_VIDEO_OUTPUT is TRUE. Setting SV_VIDEO_OUTPUT to FALSE disables live video output.
The IndigoVideo board normally synchronizes video input and output so that they have the same field rates. This is necessary if you are doing any input; however, when you are using the IndigoVideo board for output only, you will get better results if you disable this synchronization by setting SV_SLAVE to FALSE. The default value for SV_SLAVE is TRUE.
In single-frame output mode, the IndigoVideo board is configured as a 24-bit RGB framebuffer, and both live input and live output are disabled. Sending the board a still frame automatically reconfigures the board into single-frame output mode.
Use the svPutFrame() routine to send a still frame to the IndigoVideo board. The data must be in the format used by the IRIS GL lrectwrite() routine (32-bit pixels, ordered 0x00BBGGRR, that is, 1 empty byte, followed by 1 byte each of blue, green, and red).
The rows of pixels must be ordered top-to-bottom. The video capture routines also use this 32-bit RGB format. See Chapter 20, “Capturing Video from IndigoVideo,” for information on the video capture routines, and “IndigoVideo Data Formats” in Chapter 17 for information on the data formats used by IndigoVideo.
Exit single-frame mode by calling svPutFrame() with a NULL frame pointer.
Example 19-3 reads an RGB image file and sends it to the IndigoVideo board as a still frame.
Example 19-3. Sending a RGB Image as a Still Video Frame
/*
* Use video card as a 24 bit RGB framebuffer.
* ipaste SGI image file to screen, vpaste image file to video
*/
#include <stdio.h>
#include <stdlib.h>
#include <svideo.h>
#include <gl/image.h>
static void imgerror(char *);
static long getvideoparam(SVhandle, long);
static void sgiimage_to_buf(IMAGE *, unsigned long *,
unsigned long, unsigned long);
int main(int argc, char *argv[])
{
unsigned long *rgb_buf, x_size, y_size;
IMAGE* ip;
SVhandle V;
int pal_mode = 0;
char line[30];
if (argc != 2) {
fprintf(stderr, "Usage: %s imagefile\n", argv[0]);
exit(1);
}
i_seterror(imgerror);
/* Open video device */
if ((V = svOpenVideo()) == NULL {
svPerror(“open”);
exit(1);
}
/* Size image according to broadcast standard */
pal_mode = (getvideoparam(V, SV_BROADCAST) == SV_PAL);
if (pal_mode) {
x_size = SV_PAL_XMAX;
y_size = SV_PAL_YMAX;
} else {
x_size = SV_NTSC_XMAX;
y_size = SV_NTSC_YMAX;
}
/* Open image */
if((ip = iopen(argv[1],"r")) <= (IMAGE*)0) {
fprintf(stderr, "could not open image file %s\n",
argv[1]);
exit(1);
}
rgb_buf = (unsigned long *)malloc(x_size * y_size * sizeof(long));
/* Convert to RGB buffer */
sgiimage_to_buf(ip, rgb_buf, x_size, y_size);
iclose(ip);
/* Output 24-bit RGB image */
if (svPutFrame(V, (char *)rgb_buf) < 0) {
svPerror("putframe");
svCloseVideo(V);
exit(1);
}
printf("Type <Enter> to exit:");
(void) gets(line);
exit(0);
}
static void
imgerror(char *s)
{
fputs(s, stderr);
}
/* center SGI image file in buffer */
static void
sgiimage_to_buf(IMAGE *ip, unsigned long *rgb_buf, unsigned long bxsize, unsigned long bysize)
{
short *red, *green, *blue, *r, *g, *b;
int bxstart, ixstart, bystart, iystart;
int iy, by, x, nx, ny;
unsigned long *rgb;
red = malloc(ip->xsize * sizeof(short));
green = malloc(ip->xsize * sizeof(short));
blue = malloc(ip->xsize * sizeof(short));
bzero(rgb_buf,bxsize*bysize*sizeof(long));
if (ip->xsize > bxsize) {
bxstart = 0;
ixstart = (ip->xsize - bxsize)/2;
nx = bxsize;
} else {
ixstart = 0;
bxstart = (bxsize - ip->xsize)/2;
nx = ip->xsize;
}
if (ip->ysize > bysize) {
bystart = 0;
iystart = (ip->ysize - bysize)/2;
ny = bysize;
} else {
iystart = 0;
bystart = (bysize - ip->ysize)/2;
ny = ip->ysize;
}
for (iy=iystart, by=bystart; iy<iystart + ny; iy++, by++) {
getrow(ip, red, iy, 0);
getrow(ip, green, iy, 1);
getrow(ip, blue, iy, 2);
rgb = &rgb_buf[(by*bxsize) + bxstart];
r = &red[ixstart];
g = &green[ixstart];
b = &blue[ixstart];
for (x = 0; x < nx; x++) {
*rgb++ = (*b++ << 16) | (*g++ << 8) | *r++;
}
}
free(red);
free(green);
free(blue);
return 0;
}
static long
getvideoparam(SVhandle V, long arg)
{
long pvbuf[2];
pvbuf[0] = arg;
if (svGetParam(V, pvbuf, 2) < 0)
svPerror(“svGetParam”);
return pvbuf[1];
}
|