#include <stdio.h> #include <xstep.h> #include <string.h> #include <unistd.h> #include <time.h> #include <X11/extensions/Xvlib.h> #include <stdlib.h> #include <stdio.h> Atom encodingAtom; XvAdaptorInfo *adaptors; XvEncodingInfo *encodings; XSWidget *desktop, *pop, *xv; struct XVTree { char *sdevice, *schannel; int device, channel, width, height; struct XVTree *next; } *xvtree,*xvaux; int active,device,channel,width=800,height=600,pchannel,lchannel; char **channels; void xvChange(XSWidget *wid) { int a; if(pchannel==lchannel) return; for(a=0,xvaux=xvtree;xvaux;xvaux=xvaux->next,a++) if(a==pchannel) { wid=xv; if(active) XvStopVideo(wid->display,device,wid->window); device=xvaux->device; channel=xvaux->channel; XvSetPortAttribute(wid->display,device,encodingAtom,channel); XvPutVideo(wid->display,device,wid->window,wid->gc, 0,0,width,height, 0,0,width,height); active=1; lchannel=pchannel; } } void xvCreate(XSWidget *wid) { wid->bgcolor=wid->black; XSWidgetCreate(wid); // XvSetPortAttribute(wid->display,device,encodingAtom,channel); // XvPutVideo(wid->display,device,wid->window,wid->gc, // 0,0,width,height, // 0,0,width,height); } void xvGrab(XSWidget *wid) { XImage *pix; unsigned short *wptr; unsigned char *iptr,data[width*height*3]; int i,j; FILE *fp; char filename[256]; XvStopVideo(xv->display,device,xv->window); pix=XGetImage(xv->display,xv->window,0,0,640,480,0xffffff,ZPixmap); XvPutVideo(xv->display,device,xv->window,xv->gc, 0,0,width,height, 0,0,width,height); wptr=(unsigned short *)pix->data; iptr=data; for(j=i=640*480;i--;wptr++) { *iptr++ = *wptr>>8; *iptr++ = (*wptr&0x7e0)>>3; *iptr++ = *wptr<<3; } sprintf(filename,"video-%ld.ppm",time(0)); fp=fopen(filename,"w"); fprintf(fp,"P6\n%d %d\n%d\n",640,480,255); fwrite(data,j,3,fp); fprintf(stderr,"grabbed image RGB=(%x,%x,%x): %s\n", XSNamedColor(xv,"red"), XSNamedColor(xv,"green"), XSNamedColor(xv,"blue"), filename); fclose(fp); } int main(int argc,char **argv) { int version, release, a, b, c, d, n; XvAttribute *at; desktop=XSDesktop(":0",argv,argc); if(XvQueryExtension(desktop->display,&version,&release,&a,&b,&c)!=Success) exit(fprintf(stderr,"X Video Extension not available here!\n")); fprintf(stderr,"detected xVideo Extension V%dR%d:\n",version,release); XvQueryAdaptors(desktop->display,desktop->window,&n,&adaptors); for(d=a=0;a!=n;a++) { fprintf(stderr," device %ld: %s type={ %s%s%s%s%s}, ports=%ld\n", adaptors[a].base_id, adaptors[a].name, adaptors[a].type&XvInputMask ?"Input " :"", adaptors[a].type&XvOutputMask?"Output ":"", adaptors[a].type&XvVideoMask ?"Video " :"", adaptors[a].type&XvStillMask ?"Still " :"", adaptors[a].type&XvImageMask ?"Image " :"", adaptors[a].num_ports); if(!(adaptors[a].type&XvVideoMask)) continue; XvQueryEncodings(desktop->display, adaptors[a].base_id, &c, &encodings); for(b=0;b!=c;b++,d++) { fprintf(stderr," channel %ld: %s (%ldx%ld)\n", encodings[b].encoding_id, encodings[b].name, encodings[b].width, encodings[b].height); if(b==0) { channel=encodings[b].encoding_id; device=adaptors[a].base_id; } xvaux =(struct XVTree *)malloc(sizeof(struct XVTree)); xvaux->sdevice =strdup(adaptors[a].name); xvaux->schannel =strdup(encodings[b].name); xvaux->device =adaptors[a].base_id; xvaux->channel =encodings[b].encoding_id; xvaux->width =encodings[b].width; xvaux->height =encodings[b].height; xvaux->next =xvtree; xvtree=xvaux; } at=XvQueryPortAttributes(desktop->display,adaptors[a].base_id,&c); for(b=0;b!=c;b++) { fprintf(stderr," attribute %s: min/max=(%d/%d), %s%s\n", at[b].name, at[b].min_value, at[b].max_value, (at[b].flags & XvGettable) ? "R" : "", (at[b].flags & XvSettable) ? "W" : ""); } } encodingAtom = XInternAtom(desktop->display, "XV_ENCODING", False); channels=(char **)malloc(sizeof(char *)*(d+1)); for(a=0,xvaux=xvtree;xvaux;xvaux=xvaux->next,a++) channels[a]=xvaux->schannel; channels[a]=NULL; fprintf(stderr,"xVideo ready...starting graphic sub-system...\n"); xv=XSWindow(desktop,0,0,width,height+40,"XSTEPVideo!"); xv->on.create=xvCreate; XSButton(xv,-8 ,-8,72,24,"Quit",XSWindowClose); XSButton(xv,-88 ,-8,72,24,"Grab",xvGrab); XSPopup(xv,8,-8,160,21,channels,&pchannel); XSButton(xv,176,-8,72,24,"Change",xvChange); while(XSCheckEvent(desktop,!XS_BLOCK)) usleep(1); return 0; }