⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dc1394_multiview.c

📁 较新版本的libdc1394
💻 C
字号:
/****************************************************************************       Title: display video from multiple cameras/multiple cards**    $RCSfile: dc1394_multiview.c,v $**   $Revision: 1.9 $$Name:  $**       $Date: 2004/08/10 07:57:22 $**   Copyright: LGPL $Author: ddouxchamps $** Description:****    View format0-only camera video from one camera on one card,**    muliple cameras on one card, or multiple cameras on multiple cards.**** TODO:**    - Option to tile displays instead vertical stacking.****-------------------------------------------------------------------------****  $Log: dc1394_multiview.c,v $**  Revision 1.9  2004/08/10 07:57:22  ddouxchamps**  Removed extra buffering (Johann Schoonees)****  Revision 1.8  2004/03/09 08:41:44  ddouxchamps**  patch from Johann Schoonees for extra buffering****  Revision 1.7  2004/01/20 16:14:01  ddennedy**  fix segfault in dc1394_multiview****  Revision 1.6  2004/01/20 04:12:27  ddennedy**  added dc1394_free_camera_nodes and applied to examples****  Revision 1.5  2003/09/02 23:42:36  ddennedy**  cleanup handle destroying in examples; fix dc1394_multiview to use handle per camera; new example****  Revision 1.4  2002/07/27 21:24:51  ddennedy**  just increase buffers some to reduce chance of hangs****  Revision 1.3  2002/07/27 04:45:07  ddennedy**  added drop_frames option to dma capture, prepare versions/NEWS for 0.9 release****  Revision 1.2  2002/07/24 02:22:40  ddennedy**  cleanup, add drop frame support to dc1394_multiview****  Revision 1.1  2002/07/22 02:57:02  ddennedy**  added examples/dc1394_multiview to test/demonstrate dma multicapture over multiple ports******************************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/time.h>#include <sys/mman.h>#include <sys/ioctl.h>#include <sys/types.h>#include <unistd.h>#include <signal.h>#include <X11/Xlib.h>#include <X11/Xutil.h>#include <X11/extensions/Xvlib.h>#include <X11/keysym.h>#define _GNU_SOURCE#include <getopt.h>#include <libraw1394/raw1394.h>#include <libdc1394/dc1394_control.h>/* uncomment the following to drop frames to prevent delays */#define DROP_FRAMES 1#define MAX_PORTS   4#define MAX_CAMERAS 8#define NUM_BUFFERS 8/* ok the following constant should be by right included thru in Xvlib.h */#ifndef XV_YV12#define XV_YV12 0x32315659#endif#ifndef XV_YUY2#define XV_YUY2 0x32595559#endif#ifndef XV_UYVY#define XV_UYVY 0x59565955#endif/* declarations for libdc1394 */int numPorts = MAX_PORTS;raw1394handle_t handles[MAX_CAMERAS];int numCameras = 0;dc1394_cameracapture cameras[MAX_CAMERAS];nodeid_t *camera_nodes;dc1394_feature_set features;/* declarations for video1394 */char *device_name=NULL;/* declarations for Xwindows */Display *display=NULL;Window window=(Window)NULL;long width,height;long device_width,device_height;int connection=-1;XvImage *xv_image=NULL;XvAdaptorInfo *info;long format=0;GC gc;/* Other declarations */long frame_length;long frame_free;int frame=0;int adaptor=-1;int freeze=0;int average=0;int fps;int res;unsigned char *frame_buffer=NULL;static struct option long_options[]={	{"device",1,NULL,0},	{"fps",1,NULL,0},	{"res",1,NULL,0},	{"help",0,NULL,0},	{NULL,0,0,0}	};void get_options(int argc,char *argv[]){	int option_index=0;	fps=7;	res=0;		while(getopt_long(argc,argv,"",long_options,&option_index)>=0){		if(optarg){			switch(option_index){ 				/* case values must match long_options */				case 0:					device_name=strdup(optarg);					break;				case 1:					fps=atoi(optarg);					break;				case 2: 					res=atoi(optarg);					break;				}			}		if(option_index==3){			printf( "\n"			        "        %s - multi-cam monitor for libdc1394 and XVideo\n\n"				"Usage:\n"				"        %s [--fps=[1,3,7,15,30]] [--res=[0,1,2]] [--device=/dev/video1394/x]\n"				"             --fps    - frames per second. default=7,\n"				"                        30 not compatible with --res=2\n"				"             --res    - resolution. 0 = 320x240 (default),\n"				"                        1 = 640x480 YUV4:1:1, 2 = 640x480 RGB8\n"				"             --device - specifies video1394 device to use (optional)\n"				"                        default = /dev/video1394/<port#>\n"				"             --help   - prints this message\n\n"				"Keyboard Commands:\n"				"        q = quit\n"				"        < -or- , = scale -50%%\n"				"        > -or- . = scale +50%%\n"				"        0 = pause\n"				"        1 = set framerate to 1.875 fps\n"				"        2 = set framerate tp 3.75 fps\n"				"        3 = set framerate to 7.5 fps\n"				"        4 = set framerate to 15 fps\n"			    "        5 = set framerate to 30 fps\n"				,argv[0],argv[0]);			exit(0);			}		}	}/* image format conversion functions */static inlinevoid iyu12yuy2 (unsigned char *src, unsigned char *dest, int NumPixels) {  int i=0,j=0;  register int y0, y1, y2, y3, u, v;  while (i < NumPixels*3/2)    {      u = src[i++];      y0 = src[i++];      y1 = src[i++];      v = src[i++];      y2 = src[i++];      y3 = src[i++];      dest[j++] = y0;      dest[j++] = u;      dest[j++] = y1;      dest[j++] = v;      dest[j++] = y2;      dest[j++] = u;      dest[j++] = y3;      dest[j++] = v;    }}/* macro by Bart Nabbe */#define RGB2YUV(r, g, b, y, u, v)\  y = (9798*r + 19235*g + 3736*b)  / 32768;\  u = (-4784*r - 9437*g + 14221*b)  / 32768 + 128;\  v = (20218*r - 16941*g - 3277*b) / 32768 + 128;\  y = y < 0 ? 0 : y;\  u = u < 0 ? 0 : u;\  v = v < 0 ? 0 : v;\  y = y > 255 ? 255 : y;\  u = u > 255 ? 255 : u;\  v = v > 255 ? 255 : vstatic inlinevoid rgb2yuy2 (unsigned char *RGB, unsigned char *YUV, int NumPixels) {  int i, j;  register int y0, y1, u0, u1, v0, v1 ;  register int r, g, b;  for (i = 0, j = 0; i < 3 * NumPixels; i += 6, j += 4)    {      r = RGB[i + 0];      g = RGB[i + 1];      b = RGB[i + 2];      RGB2YUV (r, g, b, y0, u0 , v0);      r = RGB[i + 3];      g = RGB[i + 4];      b = RGB[i + 5];      RGB2YUV (r, g, b, y1, u1 , v1);      YUV[j + 0] = y0;      YUV[j + 1] = (u0+u1)/2;      YUV[j + 2] = y1;      YUV[j + 3] = (v0+v1)/2;    }}/* helper functions */void set_frame_length(long size, int numCameras){	frame_length=size;	fprintf(stderr,"Setting frame size to %ld kb\n",size/1024);	frame_free=0;  	frame_buffer = malloc( size * numCameras);}void display_frames(){	int i;		if(!freeze && adaptor>=0){		for (i = 0; i < numCameras; i++)		{			switch (res) {			case MODE_640x480_YUV411:				iyu12yuy2( (unsigned char *) cameras[i].capture_buffer,					frame_buffer + (i * frame_length),					(device_width*device_height) );				break;							case MODE_320x240_YUV422:			case MODE_640x480_YUV422:				memcpy( frame_buffer + (i * frame_length),					cameras[i].capture_buffer, device_width*device_height*2);				break;								case MODE_640x480_RGB:				rgb2yuy2( (unsigned char *) cameras[i].capture_buffer,					frame_buffer + (i * frame_length),					(device_width*device_height) );				break;			}		}				xv_image=XvCreateImage(display,info[adaptor].base_id,format,frame_buffer,			device_width,device_height * numCameras);		XvPutImage(display,info[adaptor].base_id,window,gc,xv_image,			0,0,device_width,device_height * numCameras,			0,0,width,height);		xv_image=NULL;	}}void QueryXv(){	int num_adaptors;	int num_formats;	XvImageFormatValues *formats=NULL;	int i,j;	char xv_name[5];		XvQueryAdaptors(display,DefaultRootWindow(display),&num_adaptors,&info);		for(i=0;i<num_adaptors;i++) {		formats=XvListImageFormats(display,info[i].base_id,&num_formats);		for(j=0;j<num_formats;j++) {			xv_name[4]=0;			memcpy(xv_name,&formats[j].id,4);			if(formats[j].id==format) {				fprintf(stderr,"using Xv format 0x%x %s %s\n",formats[j].id,xv_name,(formats[j].format==XvPacked)?"packed":"planar");				if(adaptor<0)adaptor=i;			}		}	}		XFree(formats);	if(adaptor<0)		fprintf(stderr,"No suitable Xv adaptor found");		}void cleanup(void) {	int i;	for (i=0; i < numCameras; i++)	{		dc1394_dma_unlisten( handles[i], &cameras[i] );		dc1394_dma_release_camera( handles[i], &cameras[i]);		dc1394_destroy_handle(handles[i]);	}	if ((void *)window != NULL)		XUnmapWindow(display,window);	if (display != NULL)		XFlush(display);	if (frame_buffer != NULL)		free( frame_buffer );}/* trap ctrl-c */void signal_handler( int sig) {	signal( SIGINT, SIG_IGN);	cleanup();	exit(0);}int main(int argc,char *argv[]){	XEvent xev;	XGCValues xgcv;	long background=0x010203;	unsigned int channel;	unsigned int speed;	int i, p;	raw1394handle_t raw_handle;	struct raw1394_portinfo ports[MAX_PORTS];	get_options(argc,argv);	/* process options */	switch(fps) {		case 1: fps =	FRAMERATE_1_875; break;		case 3: fps =	FRAMERATE_3_75; break;		case 15: fps = FRAMERATE_15; break;		case 30: fps = FRAMERATE_30; break;		case 60: fps = FRAMERATE_60; break;		default: fps = FRAMERATE_7_5; break;	}	switch(res) {		case 1: 			res = MODE_640x480_YUV411; 			device_width=640;			device_height=480;			format=XV_YUY2;			break;		case 2: 			res = MODE_640x480_RGB; 			device_width=640;			device_height=480;			format=XV_YUY2;			break;		default: 			res = MODE_320x240_YUV422;			device_width=320;			device_height=240;			format=XV_UYVY;			break;	}	/* get the number of ports (cards) */	raw_handle = raw1394_new_handle();    if (raw_handle==NULL) {        perror("Unable to aquire a raw1394 handle\n");        perror("did you load the drivers?\n");        exit(-1);    }		numPorts = raw1394_get_port_info(raw_handle, ports, numPorts);	raw1394_destroy_handle(raw_handle);	printf("number of ports = %d\n", numPorts);	/* get dc1394 handle to each port */	for (p = 0; p < numPorts; p++)	{		int camCount;				/* get the camera nodes and describe them as we find them */		raw_handle = raw1394_new_handle();		raw1394_set_port( raw_handle, p );		camera_nodes = dc1394_get_camera_nodes(raw_handle, &camCount, 1);		raw1394_destroy_handle(raw_handle);		/* setup cameras for capture */		for (i = 0; i < camCount; i++)		{				handles[numCameras] = dc1394_create_handle(p);			if (handles[numCameras]==NULL) {				perror("Unable to aquire a raw1394 handle\n");				perror("did you load the drivers?\n");				cleanup();				exit(-1);			}			cameras[numCameras].node = camera_nodes[i];					if(dc1394_get_camera_feature_set(handles[numCameras], cameras[numCameras].node, &features) !=DC1394_SUCCESS) 			{				printf("unable to get feature set\n");			} else {				dc1394_print_feature_set(&features);			}					if (dc1394_get_iso_channel_and_speed(handles[numCameras], cameras[numCameras].node,										 &channel, &speed) != DC1394_SUCCESS) 			{				printf("unable to get the iso channel number\n");				cleanup();				exit(-1);			}			 			if (dc1394_dma_setup_capture(handles[numCameras], cameras[numCameras].node, i+1 /*channel*/,									FORMAT_VGA_NONCOMPRESSED, res,									SPEED_400, fps, NUM_BUFFERS, DROP_FRAMES,									device_name, &cameras[numCameras]) != DC1394_SUCCESS) 			{				fprintf(stderr, "unable to setup camera- check line %d of %s to make sure\n",					   __LINE__,__FILE__);				perror("that the video mode,framerate and format are supported\n");				printf("is one supported by your camera\n");				cleanup();				exit(-1);			}							/*have the camera start sending us data*/			if (dc1394_start_iso_transmission(handles[numCameras], cameras[numCameras].node) !=DC1394_SUCCESS) 			{				perror("unable to start camera iso transmission\n");				cleanup();				exit(-1);			}			numCameras++;		}		dc1394_free_camera_nodes(camera_nodes);	}	fflush(stdout);	if (numCameras < 1) {		perror("no cameras found :(\n");		cleanup();		exit(-1);	}	switch(format){		case XV_YV12:			set_frame_length(device_width*device_height*3/2, numCameras);			break;		case XV_YUY2:		case XV_UYVY:			set_frame_length(device_width*device_height*2, numCameras);			break;		default:			fprintf(stderr,"Unknown format set (internal error)\n");			exit(255);	}	/* make the window */	display=XOpenDisplay(getenv("DISPLAY"));	if(display==NULL)	{		fprintf(stderr,"Could not open display \"%s\"\n",getenv("DISPLAY"));		cleanup();		exit(-1);	}		QueryXv();		if ( adaptor < 0 )	{		cleanup();		exit(-1);	}		width=device_width;	height=device_height * numCameras;	window=XCreateSimpleWindow(display,DefaultRootWindow(display),0,0,width,height,0,		WhitePixel(display,DefaultScreen(display)),		background);			XSelectInput(display,window,StructureNotifyMask|KeyPressMask);	XMapWindow(display,window);	connection=ConnectionNumber(display);		gc=XCreateGC(display,window,0,&xgcv);			/* main event loop */		while(1){		dc1394_dma_multi_capture(cameras, numCameras);				display_frames();		XFlush(display);		while(XPending(display)>0){			XNextEvent(display,&xev);			switch(xev.type){				case ConfigureNotify:					width=xev.xconfigure.width;					height=xev.xconfigure.height;					display_frames();					break;				case KeyPress:					switch(XKeycodeToKeysym(display,xev.xkey.keycode,0)){						case XK_q:						case XK_Q:							cleanup();							exit(0);							break;						case XK_comma:						case XK_less:							width=width/2;							height=height/2;							XResizeWindow(display,window,width,height);							display_frames();							break;						case XK_period:						case XK_greater:							width=2*width;							height=2*height;							XResizeWindow(display,window,width,height);							display_frames();							break;						case XK_0:							freeze = !freeze;							break;						case XK_1:							fps =	FRAMERATE_1_875; 							for (i = 0; i < numCameras; i++)								dc1394_set_video_framerate(handles[i], cameras[i].node, fps);							break;						case XK_2:							fps =	FRAMERATE_3_75; 							for (i = 0; i < numCameras; i++)								dc1394_set_video_framerate(handles[i], cameras[i].node, fps);							break;						case XK_4:							fps = FRAMERATE_15; 							for (i = 0; i < numCameras; i++)								dc1394_set_video_framerate(handles[i], cameras[i].node, fps);							break;						case XK_5: 							fps = FRAMERATE_30;							for (i = 0; i < numCameras; i++)								dc1394_set_video_framerate(handles[i], cameras[i].node, fps);							break;						case XK_3:							fps = FRAMERATE_7_5; 							for (i = 0; i < numCameras; i++)								dc1394_set_video_framerate(handles[i], cameras[i].node, fps);							break;						}					break;				}			} /* XPending */			for (i = 0; i < numCameras; i++)			{				dc1394_dma_done_with_buffer(&cameras[i]);			}				} /* while not interrupted */	exit(0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -