Re: Video texture in performer animation ...

New Message Reply Date view Thread view Subject view Author view

JAVIER CASTELLAR (javier++at++mar.madrid.sgi.com)
Wed, 4 Jan 1995 12:52:53 -0800


Hi all,

Regarding the live video texturing questions:
a) It works fine (do not beleave rumours about Sirius).
b) It works at full perfomance (if you don't beleave SGI please watch the
Spanish TV (A3)).

Mainly the live video texturing programming works as follows:

0) Initialize the VideoLibrary with a video source node attached to a texture
drain node. You have to select FIELDS or FRAMES. If you need fields you have to
use Sirius 1.0.2 > software release.

[Attached to this email please find a VL set up example to texture video on a
polygon]

1) You have to define a texture with some especific features to be updated from
video:
        It must have a sizes of power of two (1024x1024 or 1024x512).
        It has to be NON MIPMAPPED
        It has to use the FAST_DEFINE texture prop.
(it will let you page this texture either from live video frames/fields or from
main memory)

    /*
     * create a new texture from shared memory,
     * load a texture file and add texture to geostate
     */
        tx = pfNewTex(arena);
        pfTexRepeat(tx, PFTEX_WRAP, PFTEX_CLAMP);
        pfTexFilter(tx, PFTEX_MINFILTER, PFTEX_BILINEAR);
        pfTexFilter(tx, PFTEX_MAGFILTER, PFTEX_BILINEAR);
        pfTexFormat(tx, PFTEX_FAST_DEFINE, PF_ON);
        pfTexFormat(tx, PFTEX_INTERNAL_FORMAT, PFTEX_RGB_5);
                /* frames, in fields is different */
        pfTexImage(tx, NULL, SIR_VEN_16BIT_TEXEL, 1024, 1024 , 0);
        pfGStateAttr(gst, PFSTATE_TEXTURE, tx);

2) When you are running in the real time loop, you have to perform a draw call
back to update the texture that you had defined as FAST_DEFINE. This callback
will swap the live video frame buffers which are located at the Sirius board to
the texture memory in the place (texture id) you have prepared in (1).
        This GL callbacks are based on the subtexload GL call (see details on
the manual pages). In order to obtain the GL texture id you should use the
pfGetGLHandle call to get the GL texture id (in performer there is no texture
id exposed, but fortunatelly the give you a way to obtain it using the pf API).

        Subtextload works fine on 5.2> machines.

        Be aware about the fact that the texture to be video paged MUST BE
binded at the time in which you call subtexload. Be aware also about the
texture matrix you are using at the time in which you page the video texture.

[Attached to this mail please find vidtotex.c; an example in VL+GL wich explain
it (texture matrix, subtexload ...) (it texture live video onto a polygon)]

COMMENTS:
        1) Be very aware about the vof you are using on the RealityEngine video
output. Be aware also about the genlocking between the video source and the
Sirius board.
        2) Be aware also about the texture memory manegement which you are
performing. The order in which you are actually defining the textures is VERY
IMPORTANT, if you are using also mipmapped textures on the scene, be carefull
and load it AFTER the definition on the live video texture. It will save you s
LOT of texture memory fragmentation.
        3) The Sirius programming guide is a VERY GOOD reference point about
this issues. You will find also very interesting examples in

/usr/people/4Dgifts/examples/dmedia/video/sirius in IRIX 5.3 (in 5.2 you will
find also the same examples around the 4Dgifts examples).

Hope to help.

-Javier (OVERLOADED)

-- 
********************************************************************
*  Javier Castellar     * Email:	javier++at++madrid.sgi.com      *
*  Systems Engineer	* Vmail:	x59665                     *
*     	   Gfx guru     * Phone:	++34-1-4429077             *
* Silicon Graphics Spain* Fax:		++34-1-4420150             *
********************************************************************
  Nobody said that the life was a fair play
				Javier Castellar

/* * vidtotex.c * This VL program demonstrates the Sirius Video board video->texture ability. * * Copyright 1994, Silicon Graphics, Inc. * All Rights Reserved. * * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.; * the contents of this file may not be disclosed to third parties, copied or * duplicated in any form, in whole or in part, without the prior written * permission of Silicon Graphics, Inc. * * RESTRICTED RIGHTS LEGEND: * Use, duplication or disclosure by the Government is subject to restrictions * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data * and Computer Software clause at DFARS 252.227-701.0, and/or in similar or * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished - * rights reserved under the Copyright Laws of the United States. */

#include <stdlib.h> #include <stdio.h> #include <getopt.h> #include <gl.h> #include <device.h> #include <vl/vl.h> #include <vl/dev_sirius.h>

/* * Following definitons are the texture matrix defines. Look in * the GL programmers guide for more details. */ #define XSIZE 64.0 #define YSIZE 64.0

static float texture_matrix[4][4] = { 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 }; static float idmat[4][4] = { 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 };

static float t0[2] = {0.0, 0.0 }; static float t1[2] = {1.0, 0.0 }; static float t2[2] = {1.0, 1.0 }; static float t3[2] = {0.0, 1.0 };

static float v0[3] = {-XSIZE, -YSIZE, 0.0}; static float v1[3] = { XSIZE, -YSIZE, 0.0}; static float v2[3] = { XSIZE, YSIZE, 0.0}; static float v3[3] = {-XSIZE, YSIZE, 0.0};

static float tevps[] = {TX_NULL};

/* * texture defines */ int texture_id, num_components; float s_scale, t_scale, s_fraction, t_fraction; int texture_format; int texformat;

/* * VL defines */ VLControlValue size, timing, tex; VLControlValue format; VLControlValue cap_type; VLServer svr; VLPath path; VLNode src; VLNode drn;

/* * function prototypes */ void usage(int, char **); void OpenWindow(int, char **); int CreateTexture(void); void DisplayNewTexture(void); void cleanup(void); void ProcessEvents(void); void UpdateTimingFormat(void);

int DoFields = 0;

int main(int argc, char **argv) {

int c, insrc = VL_ANY; int device = VL_ANY; short dev, val;

texformat = 5; /* Parse the input string */ while ((c = getopt(argc, argv, "n:v:t:hF")) != EOF ) { switch (c) { case 'n': device = atoi(optarg); /* user can override default device */ break; case 't': texformat = atoi(optarg); break; case 'v': insrc = atoi(optarg); break; case 'F': DoFields = 1; break; case 'h': default: usage(argc, argv); exit(1); } }

/* open the server */ if (!(svr = vlOpenVideo(""))) { printf("couldn't open video\n"); exit(1); }

/* Get the Video source */ src = vlGetNode(svr, VL_SRC, VL_VIDEO, insrc); /* Get the Texture drain */ drn = vlGetNode(svr, VL_DRN, VL_TEXTURE, 0);

/* Create path */ path = vlCreatePath(svr, device, src, drn); if (path < 0) { vlPerror("vlCreatePath"); exit(1); }

/* setup path */ if (vlSetupPaths(svr, (VLPathList)&path, 1, VL_SHARE, VL_SHARE) < 0) { vlPerror("vlSetupPaths"); exit(1); } /* select the appropriate events */ if (vlSelectEvents(svr, path, VLStreamPreemptedMask | VLControlChangedMask ) < 0) { vlPerror("Select Events"); exit(1); } if(DoFields) cap_type.intVal = VL_CAPTURE_NONINTERLEAVED; else cap_type.intVal = VL_CAPTURE_INTERLEAVED; if (vlSetControl(svr, path, drn, VL_CAP_TYPE, &cap_type) <0) { vlPerror("VlSetControl"); exit(1); }

UpdateTimingFormat(); OpenWindow(argc, argv); texture_id = 1; CreateTexture(); loadmatrix(texture_matrix); /* Set the Texture packing mode */ if (vlSetControl(svr, path, drn, VL_PACKING, &tex) <0) { vlPerror("VlSetControl"); exit(1); }

/* Set the viewing preferences. Look at GL manual for more details */ mmode(MVIEWING); loadmatrix(idmat); ortho2(0.0, size.xyVal.x * 1.0, 0.0, size.xyVal.y * 1.0);

vlBeginTransfer(svr, path, 0, NULL);

while (TRUE) { if (qtest()) { dev = qread(&val); if (dev == ESCKEY) exit(0); } /* Check for VL events if any ... */ ProcessEvents(); /* Next frame of data */ DisplayNewTexture(); swapbuffers(); } }

void usage(int argc, char **argv) { fprintf(stderr, "Usage: %s [-n#] [-v#]\n", argv[0]); fprintf(stderr, " -n# video device number (as reported by vlinfo)\n"); fprintf(stderr, " -v# video input number (as reported by vlinfo)\n"); fprintf(stderr, " -F# do Fields \n"); }

/* * OpenWindow: Opens a GL window of the correct size as determined by * the timing bvaluse on the source node. */ void OpenWindow(int argc, char **argv) { prefsize(size.xyVal.x, size.xyVal.y); foreground(); winopen(argv[0]); RGBmode(); doublebuffer(); gconfig(); dither(DT_OFF); qdevice(ESCKEY); }

/* * CreateTexture: Create a texture map with correct attributes. */ int CreateTexture() { int t_width, t_height; static float tex_props[] = { TX_MINFILTER, TX_POINT, TX_MAGFILTER, TX_POINT, TX_INTERNAL_FORMAT, TX_RGB_5, TX_FAST_DEFINE, TX_WRAP, TX_CLAMP, TX_NULL };

switch(texformat) { case 4: num_components = SIR_VEN_16BIT_TEXEL; tex.intVal = SIR_TEX_PACK_RGBA_4; texture_format = SIR_VEN_16BIT_TEXEL; /* texture format dependant */ tex_props[5] = TX_RGBA_4; /* this too */ break; case 5: num_components = SIR_VEN_16BIT_TEXEL; tex.intVal = SIR_TEX_PACK_RGB_5; texture_format = SIR_VEN_16BIT_TEXEL; /* texture format dependant */ tex_props[5] = TX_RGB_5; /* this too */ break; case 8: num_components = SIR_VEN_32BIT_TEXEL; tex.intVal = SIR_TEX_PACK_RGBA_8; texture_format = SIR_VEN_32BIT_TEXEL; /* texture format dependant */ tex_props[5] = TX_RGBA_8; /* this too */ break; default: num_components = SIR_VEN_16BIT_TEXEL; tex.intVal = SIR_TEX_PACK_RGB_5; texture_format = SIR_VEN_16BIT_TEXEL; /* texture format dependant */ tex_props[5] = TX_RGB_5; /* this too */ break; }

tex_props[1] = TX_POINT; tex_props[3] = TX_POINT;

/* 625 textures are bigger than 525 textures */ if ((timing.intVal == VL_TIMING_525_SQ_PIX) || (timing.intVal == VL_TIMING_525_CCIR601)) { t_width = 1024; t_height = 512; } else { t_width = 1024; t_height = 1024; }

s_scale = (size.xyVal.x-1) / (float)t_width; t_scale = size.xyVal.y / (float)t_height;

/* Sirius always transfers 768 pixels */ s_fraction = 768. / (float)t_width; /* for all */ t_fraction = size.xyVal.y / (float)t_height;

if (DoFields) t_height=t_height>>1; texdef2d(texture_id, num_components, t_width, t_height, (void *)0, 0, tex_props);

texture_matrix[0][0] = s_scale; texture_matrix[1][1] = -t_scale; texture_matrix[3][1] = t_scale;

tevdef(1, 0, tevps);

texbind(TX_TEXTURE_0, texture_id); tevbind(0, 1); mmode(MTEXTURE); }

/* * DisplayNewTexture: Display a new texture. This routine is called at 30 * Hz for 525 timing and 25Hz for 625 timing. */ void DisplayNewTexture() { /* Load the texture from Sirius to Texture memory */ subtexload(TX_TEXTURE_0, texture_id, 0.0, s_fraction, 0.0, t_fraction, 0, (unsigned long *)0, texture_format);

/* Do size calculations */ v0[0] = 0.; v0[1] = 0.; v1[0] = size.xyVal.x; v1[1] = 0.; v2[0] = size.xyVal.x; v2[1] = size.xyVal.y; v3[0] = 0.; v3[1] = size.xyVal.y;

/* draw full size video */ cpack(0xffffffff); bgnpolygon(); t2f(t0); v2f(v0); t2f(t1); v2f(v1); t2f(t2); v2f(v2); t2f(t3); v2f(v3); endpolygon(); }

void cleanup() { vlEndTransfer(svr, path); vlDestroyPath(svr, path); vlCloseVideo(svr); exit(0); }

void ProcessEvents() { VLEvent ev;

/* Check to see if any controls changed or if the video * path has been pre-empted. */ if (vlCheckEvent(svr, VLControlChangedMask| VLStreamPreemptedMask, &ev) == -1) { return; } switch(ev.reason) { case VLStreamPreempted: cleanup(); exit(0); break; case VLControlChanged: switch(ev.vlcontrolchanged.type) { case VL_TIMING: case VL_SIZE: case VL_PACKING: UpdateTimingFormat(); prefsize(size.xyVal.x, size.xyVal.y); winconstraints(); CreateTexture(); loadmatrix(texture_matrix); mmode(MVIEWING); loadmatrix(idmat); ortho2(0.0, size.xyVal.x * 1.0, 0.0, size.xyVal.y * 1.0); break; default: break; } break; default: break; } }

void UpdateTimingFormat() { /* Get the timing from input source */ if (vlGetControl(svr, path, src, VL_TIMING, &timing) < 0) { vlPerror("vlGetControl"); exit(1); }

/* Set texture drain's timing to input source */ if (vlSetControl(svr, path, drn, VL_TIMING, &timing) < 0) { vlPerror("vlSetControl"); exit(1); }

if (vlGetControl(svr, path, src, VL_SIZE, &size) < 0) { vlPerror("vlSetupPaths"); exit(1); } }


New Message Reply Date view Thread view Subject view Author view

This archive was generated by hypermail 2.0b2 on Mon Aug 10 1998 - 17:50:49 PDT

This message has been cleansed for anti-spam protection. Replace '++at++' in any mail addresses with the '@' symbol.