Anita Kishore (kishore++at++triavest.com)
Wed, 15 Oct 1997 17:25:31 -0700
In the program that I am trying, I do the foll. steps:
- configure DIVO video src, drn nodes etc.
- get video image in dmBuffer
- configure pf texture to receive video image
using the pfTexLoadMode call with PFTEX_SOURCE_IMAGE
- every frame in the channel Draw callback
- get image dataPtr from dmBuffer
- use this image ptr in pfTexImage call
- load tex into tram
The DIVO related parts are taken from the opnGL example.
The result that I get is totally bad. The problems that I have seen so far
are:
- I don't get a valid dmBuffer every frame
- the mapped image is all garbage
- giving the scale factors in the tex matrix does not work properly
- I am sure there are other problems too.
I am enclosing my code with this mail for anyone interested in it.
Any help with this idea or someother idea for mapping live video
onto texture is welcome. Too bad that DIVO can't transfer video
directly into TRAM like Sirius. I wonder what the reason can be...
thanks
-anita
P.S: I am using IRIX 6.4.1, pf 2.1 on Onyx2 IR
----------------------------------------------------------------------------
File : divo_lvideo.c
----------------------------------------------------------------------------
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <vl/vl.h>
#include <Performer/pf.h>
#define GEO_SIZE 1.0f
typedef struct {
Display * Dsp;
pfPipeWindow * pw;
pfGeoState * gst;
VLServer vlServer;
VLPath vlPath;
} lvStruct;
lvStruct *lvData;
/* VL variables */
VLBuffer buffer;
int frames = 0;
VLNode vlSrc, vlDrn;
VLControlValue size;
VLTransferDescriptor xferDesc;
int vlTexWidth, vlTexHeight;
int F1_is_first;
int frameSize;
int cspace = VL_COLORSPACE_RGB;
int packing = VL_PACKING_4444_8;
int capType = VL_CAPTURE_NONINTERLEAVED;
//int capType = VL_CAPTURE_INTERLEAVED;
GLXVideoSourceSGIX videosource;
DMbuffer dmbuf;
DMbufferpool pool;
uint **dataPtr;
pfTexture **tex;
void *arena = NULL;
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 int
loadTextureMatrixCB(pfGeoState *gs, void *userData)
{
pfMatrix *tmat = (pfMatrix *)(userData);
glMatrixMode(GL_TEXTURE);
pfLoadMatrix(*tmat);
glMatrixMode(GL_MODELVIEW);
return 0;
}
static int
loadIDMatrixCB(pfGeoState *gs, void *userData)
{
glMatrixMode(GL_TEXTURE);
pfLoadMatrix(idmat);
glMatrixMode(GL_MODELVIEW);
return 0;
}
pfGeoSet *makeGeometry(void)
{
pfTexEnv *tenv;
pfGeoSet *gset;
pfGeoState *gst;
static pfVec3 verts[] ={{-GEO_SIZE, 0, -GEO_SIZE},
{ GEO_SIZE, 0, -GEO_SIZE},
{ GEO_SIZE, 0, GEO_SIZE},
{-GEO_SIZE, 0, GEO_SIZE}};
static ushort vindex[] ={0, 1, 2, 3}; /* front */
static pfVec3 norms[] ={{ 0.0f, -1.0f, 0.0f}};
static ushort nindex[] ={0};
static pfVec2 tcoords[] ={{0.0f, 0.0f},
{1.0f, 0.0f},
{1.0f, 1.0f},
{0.0f, 1.0f}};
static ushort tindex[] ={0, 1, 2, 3};
gset = pfNewGSet(arena);
pfGSetAttr(gset, PFGS_COORD3, PFGS_PER_VERTEX, verts, vindex);
pfGSetAttr(gset, PFGS_NORMAL3, PFGS_PER_PRIM, norms, nindex);
pfGSetAttr(gset, PFGS_TEXCOORD2, PFGS_PER_VERTEX, tcoords, tindex);
pfGSetPrimType(gset, PFGS_QUADS);
pfGSetNumPrims(gset, 1);
lvData->gst = gst = pfNewGState(arena);
pfGStateMode(gst, PFSTATE_ENTEXTURE, 1);
pfGSetGState(gset, gst);
*tex = pfNewTex(arena);
pfLoadTexFile(*tex, "/usr/share/Performer/data/bark.rgb");
pfGStateAttr(gst, PFSTATE_TEXTURE, *tex);
tenv = pfNewTEnv(arena);
pfTEnvMode(tenv, PFTE_DECAL);
pfGStateAttr(gst, PFSTATE_TEXENV, tenv);
return gset;
}
pfGroup *MkScene()
{
pfGroup *group;
pfGeoSet *geometry;
pfGeode *geode;
group = pfNewGroup();
geode = pfNewGeode();
geometry = makeGeometry();
pfAddGSet(geode, geometry);
pfAddChild(group, geode);
return group;
}
void UpdateTiming(VLControlValue *vlTiming)
{
VLControlValue dominance;
if (vlGetControl(lvData->vlServer, lvData->vlPath, vlSrc,
VL_TIMING, vlTiming) <0)
{
vlPerror("VlGetControl");
exit(1);
}
if (vlGetControl(lvData->vlServer, lvData->vlPath, vlSrc,
VL_FIELD_DOMINANCE, &dominance) <0)
{
vlPerror("VlGetControl");
exit(1);
}
F1_is_first = ( (vlTiming->intVal == VL_TIMING_625_SQ_PIX) ||
(vlTiming->intVal == VL_TIMING_625_CCIR601) );
F1_is_first ^= (dominance.intVal == VL_F2_IS_DOMINANT);
}
void VideoInit(VLControlValue *vlSize, VLControlValue *vlTiming,
VLControlValue *vlTexPack)
{
VLControlValue val;
DMparams* plist;
if (!(lvData->vlServer = vlOpenVideo("")))
{
printf("couldn't open connection to VL server\n");
exit(1);
}
vlDrn = vlGetNode(lvData->vlServer, VL_DRN, VL_MEM, VL_ANY);
vlSrc = vlGetNode(lvData->vlServer, VL_SRC, VL_VIDEO, VL_ANY);
if ((lvData->vlPath = vlCreatePath(lvData->vlServer,
VL_ANY, vlSrc, vlDrn)) < 0)
{
vlPerror("vlCreatePath");
exit(1);
}
if (vlSetupPaths(lvData->vlServer, (VLPathList)&lvData->vlPath,
1, VL_SHARE, VL_SHARE) < 0)
{
vlPerror("vlSetupPaths");
exit(1);
}
UpdateTiming(vlTiming);
vlSelectEvents(lvData->vlServer, lvData->vlPath,
VLStreamStartedMask | VLTransferCompleteMask |
VLTransferFailedMask | VLStreamStoppedMask);
vlTexPack->intVal = packing;
if (vlSetControl(lvData->vlServer, lvData->vlPath,
vlDrn, VL_PACKING, vlTexPack) < 0)
{
vlPerror("vlSetControl(VL_PACKING)");
exit(1);
}
val.intVal = cspace;
if (vlSetControl(lvData->vlServer, lvData->vlPath,
vlDrn, VL_COLORSPACE, &val) < 0)
{
vlPerror("vlSetControl(VL_PACKING)");
exit(1);
}
val.intVal = capType;
if (vlSetControl(lvData->vlServer, lvData->vlPath,
vlDrn, VL_CAP_TYPE, &val) < 0)
{
vlPerror("vlSetControl(VL_CAP_TYPE)");
exit(1);
}
vlGetControl(lvData->vlServer, lvData->vlPath, vlDrn, VL_SIZE, vlSize);
fprintf(stderr,"After vlGetControl : xsize is %d, ysize is %d\n",
vlSize->xyVal.x, vlSize->xyVal.y);
frameSize = vlGetTransferSize(lvData->vlServer, lvData->vlPath);
if (dmParamsCreate(&plist))
{
printf("dmParamsCreate failed!\n");
exit(1);
}
dmBufferSetPoolDefaults(plist, 2, frameSize, DM_TRUE, DM_FALSE);
vlDMGetParams(lvData->vlServer, lvData->vlPath, vlDrn, plist);
if (dmBufferCreatePool(plist, &pool) != DM_SUCCESS)
printf("dmBufferCreatePool failed %s\n", dmGetError(0, 0));
dmParamsDestroy(plist);
if (!pool)
{
vlPerror("NULL pool");
exit(1);
}
/* Associate the pool with the lvData->vlPath */
if (vlDMPoolRegister(lvData->vlServer, lvData->vlPath, vlDrn, pool))
{
vlPerror("vlDMPoolRegister");
dmBufferDestroyPool(pool);
exit(1);
}
xferDesc.mode = VL_TRANSFER_MODE_CONTINUOUS;
xferDesc.count = 0;
xferDesc.delay = 0;
xferDesc.trigger = VLTriggerImmediate;
fprintf ( stderr, "video init done\n" );
}
static void
setVideoTextureParameters(VLControlValue * vlSize,
VLControlValue * vlTiming, VLControlValue * vlTexPack )
{
pfMatrix *tmat;
float s_scale, t_scale;
float vheight = vlSize->xyVal.y * 2.0;
/*
if ((vlTiming->intVal == VL_TIMING_525_SQ_PIX)
|| (vlTiming->intVal == VL_TIMING_525_CCIR601)) {
vlTexWidth = 1024;
vlTexHeight = 512;
} else {
vlTexWidth = 1024;
vlTexHeight = 1024;
}
*/
/*
* texture dimensions must be powers of two. Find the smallest powers
* of two that are greater than or equal to image width and height.
*/
vlTexWidth = 1;
while (vlTexWidth < vlSize->xyVal.x) {
vlTexWidth <<= 1;
}
vlTexHeight = 1;
while (vlTexHeight < vheight) {
vlTexHeight <<= 1;
}
/* create texture matrix for scaling texcoords to valid part of texture */
tmat = (pfMatrix*) pfCalloc(sizeof(pfMatrix), 1, pfGetSharedArena() );
pfMakeIdentMat(*tmat);
s_scale = vlSize -> xyVal.x / (float) vlTexWidth;
//t_scale = vlSize -> xyVal.y / (float) vlTexHeight;
t_scale = vheight / (float) vlTexHeight;
printf("**** vlSize.x = %d vlSize.y = %d vlTexWidth = %d vlTexHeight = %d\n",
vlSize -> xyVal.x, vlSize -> xyVal.y, vlTexWidth, vlTexHeight);
/*
(*tmat)[0][0] = s_scale;
(*tmat)[1][1] = -t_scale;
(*tmat)[3][1] = t_scale;
*/
(*tmat)[1][1] = -1;
/* gset callbacks to manage texture matrix - put matrix in userData */
pfGStateFuncs(lvData->gst, loadTextureMatrixCB, loadIDMatrixCB, tmat);
/* Now configure the pf texture */
pfTexFormat(*tex, PFTEX_SUBLOAD_FORMAT, 1);
pfTexFilter(*tex, PFTEX_MINFILTER, PFTEX_BILINEAR);
pfTexImage(*tex, *dataPtr, 4, vlTexWidth, vlTexHeight/2, 1);
pfTexLoadSize(*tex, vlSize->xyVal.x, vlSize->xyVal.y/2);
pfTexFormat(*tex, PFTEX_INTERNAL_FORMAT, PFTEX_RGB_5);
pfTexLoadMode(*tex, PFTEX_LOAD_SOURCE, PFTEX_SOURCE_IMAGE);
}
void beginVideo()
{
vlBeginTransfer(lvData->vlServer, lvData->vlPath, 1, &xferDesc);
}
void
OpenPipeWin (pfPipeWindow *pw)
{
VLControlValue vlSize, vlTiming, vlTexPack;
pfOpenPWin(pw);
pfApplyLModel(pfNewLModel(NULL));
VideoInit (&vlSize, &vlTiming, &vlTexPack );
setVideoTextureParameters(&vlSize, &vlTiming, &vlTexPack );
beginVideo();
}
void
DrawChannel (pfChannel *chan, void *data)
{
int ret;
ret = vlDMBufferGetValid(lvData->vlServer, lvData->vlPath,
vlDrn, &dmbuf);
if (ret == VLSuccess)
{
*dataPtr = dmBufferMapData(dmbuf);
if (*dataPtr == NULL)
{
printf("dmBufferMapData failed %s\n", dmGetError(0,0));
exit(1);
}
else
{
//pfTexImage(*tex, *dataPtr, 4, vlTexWidth, vlTexHeight/2, 1);
dmBufferFree(dmbuf);
}
}
else if (vlErrno!=VLAgain)
{
vlPerror("vlDMBufferGetValid");
exit(1);
}
else if (vlErrno==VLAgain)
printf("Bad dmbuf\n");
pfClearChan(chan);
pfLoadTex(*tex);
pfDraw();
}
int main(int argc, char **argv)
{
pfScene *scene;
pfPipe *p;
pfPipeWindow *pw;
pfChannel *chan;
pfSphere bsphere;
pfCoord view;
pfNode *root;
pfLightSource *ls;
pfInit();
arena = pfGetSharedArena();
tex = (pfTexture **) pfMalloc(sizeof(pfTexture *), arena);
lvData = (lvStruct *)pfMalloc( sizeof(lvStruct), arena);
dataPtr = (uint **)pfMalloc( sizeof(uint *), arena);
*dataPtr = NULL;
pfMultiprocess(PFMP_DEFAULT);
pfConfig();
scene = pfNewScene();
root = (pfNode *) MkScene();
pfAddChild(scene, root);
pfGetNodeBSphere (scene, &bsphere);
/* Configure and open GL window */
p = pfGetPipe(0);
lvData->pw = pw = pfNewPWin(p);
pfPWinName(pw, argv[0]);
pfPWinOriginSize(pw, 0, 0, 500, 500);
lvData->Dsp = pfGetCurWSConnection();
pfPWinConfigFunc(pw, OpenPipeWin);
pfConfigPWin(pw);
/* Create and configure a pfChannel. */
chan = pfNewChan(p);
pfChanScene(chan, scene);
pfChanNearFar(chan, 1.0f, 10.0f * bsphere.radius);
pfChanFOV(chan, 45.0f, 0.0f);
pfCopyVec3(view.xyz, bsphere.center);
view.xyz[PF_Y] -= 3.0f * bsphere.radius;
pfSetVec3(view.hpr, 0.0f, 0.0f, 0.0f);
pfChanView(chan, view.xyz, view.hpr);
pfChanTravFunc(chan, PFTRAV_DRAW, DrawChannel);
/* Create a pfLightSource and attach it to scene. */
ls = pfNewLSource();
pfLSourcePos(ls, view.xyz[0], view.xyz[1], view.xyz[2], 1.0f);
pfAddChild(scene, ls);
while (1)
{
pfSync();
pfFrame();
}
pfExit();
}
-----------------------------------------------------------------------------
File : makefile
-----------------------------------------------------------------------------
SHELL = /bin/sh
#-- provide a list of alternate locations for file searches
UNIQUE = .
#-- alternate locatins for included files
INCLUDE = \
-I/usr/include/Performer
#SRCLIBOPT=_igl
SRCLIBOPT=_ogl
PERFORMER = \
-lpf${SRCLIBOPT}
#-- IRIX 4.x uses shared gl {gl_s} library {System-V Make lacks #if movietex.cs}#LIBGL1 = -lgl
LIBGL1 = -lGL
LIBGL2 = ${LIBGL1:.4=_s}
LIBGL = ${LIBGL2:.5=}
SYSTEM = \
-lInventor \
-lvl \
-ldmedia \
${LIBGL} \
-lX11 \
-lm \
-lfpe \
-lC
LIBRARIES = \
${PERFORMER} ${SYSTEM}
#-- select c-compiler options
CFLAGS = -xansi -g -D__STDC__ ${INCLUDE} ${COPT} -DPF_C_API=1 \
-DPF_CPLUSPLUS_API=0 \
-DPF_MAJOR_VERSION=2 -Xcpluscomm -mips2 -32
#-DIRISGL
#-- base name of program
TARGET = divo_lvideo
#-- object files from which target built {some are in the common directory}
OBJECTS = \
divo_lvideo.o
${TARGET}: ${OBJECTS}
${CC} ${CFLAGS} -o $++at++ ${OBJECTS} ${LIBRARIES}
#-- objects are built from either unique or common files
divo_lvideo.o: ${UNIQUE}/divo_lvideo.c
${CC} ${CFLAGS} -c divo_lvideo.c -o $++at++
clean :
rm -f divo_lvideo divo_lvideo.o
=======================================================================
List Archives, FAQ, FTP: http://www.sgi.com/Technology/Performer/
Submissions: info-performer++at++sgi.com
Admin. requests: info-performer-request++at++sgi.com
This archive was generated by hypermail 2.0b2 on Mon Aug 10 1998 - 17:56:05 PDT