00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <sys/ioctl.h>
00021 #include <sys/types.h>
00022 #include <sys/stat.h>
00023 #include <sys/mman.h>
00024 #include <fcntl.h>
00025 #include <unistd.h>
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include <linux/types.h>
00030 #include <linux/videodev.h>
00031 #include <AR/config.h>
00032 #include <AR/ar.h>
00033 #include <AR/video.h>
00034 #include "ccvt.h"
00035 #ifdef USE_EYETOY
00036 #include "jpegtorgb.h"
00037 #endif
00038
00039 #define MAXCHANNEL 10
00040
00041 static AR2VideoParamT *gVid = NULL;
00042
00043 int arVideoDispOption( void )
00044 {
00045 return ar2VideoDispOption();
00046 }
00047
00048 int arVideoOpen( char *config )
00049 {
00050 if( gVid != NULL ) {
00051 printf("Device has been opened!!\n");
00052 return -1;
00053 }
00054 gVid = ar2VideoOpen( config );
00055 if( gVid == NULL ) return -1;
00056
00057 return 0;
00058 }
00059
00060 int arVideoClose( void )
00061 {
00062 int result;
00063
00064 if( gVid == NULL ) return -1;
00065
00066 result = ar2VideoClose(gVid);
00067 gVid = NULL;
00068 return (result);
00069 }
00070
00071 int arVideoInqSize( int *x, int *y )
00072 {
00073 if( gVid == NULL ) return -1;
00074
00075 return ar2VideoInqSize( gVid, x, y );
00076 }
00077
00078 ARUint8 *arVideoGetImage( void )
00079 {
00080 if( gVid == NULL ) return NULL;
00081
00082 return ar2VideoGetImage( gVid );
00083 }
00084
00085 int arVideoCapStart( void )
00086 {
00087 if( gVid == NULL ) return -1;
00088
00089 return ar2VideoCapStart( gVid );
00090 }
00091
00092 int arVideoCapStop( void )
00093 {
00094 if( gVid == NULL ) return -1;
00095
00096 return ar2VideoCapStop( gVid );
00097 }
00098
00099 int arVideoCapNext( void )
00100 {
00101 if( gVid == NULL ) return -1;
00102
00103 return ar2VideoCapNext( gVid );
00104 }
00105
00106
00107
00108 int ar2VideoDispOption( void )
00109 {
00110 printf("ARVideo may be configured using one or more of the following options,\n");
00111 printf("separated by a space:\n\n");
00112 printf("DEVICE CONTROLS:\n");
00113 printf(" -dev=filepath\n");
00114 printf(" specifies device file.\n");
00115 printf(" -channel=N\n");
00116 printf(" specifies source channel.\n");
00117 printf(" -noadjust\n");
00118 printf(" prevent adjusting the width/height/channel if not suitable.\n");
00119 printf(" -width=N\n");
00120 printf(" specifies expected width of image.\n");
00121 printf(" -height=N\n");
00122 printf(" specifies expected height of image.\n");
00123 printf(" -palette=[RGB|YUV420P]\n");
00124 printf(" specifies the camera palette (WARNING:all are not supported on each camera !!).\n");
00125 printf("IMAGE CONTROLS (WARNING: every options are not supported by all camera !!):\n");
00126 printf(" -brightness=N\n");
00127 printf(" specifies brightness. (0.0 <-> 1.0)\n");
00128 printf(" -contrast=N\n");
00129 printf(" specifies contrast. (0.0 <-> 1.0)\n");
00130 printf(" -saturation=N\n");
00131 printf(" specifies saturation (color). (0.0 <-> 1.0) (for color camera only)\n");
00132 printf(" -hue=N\n");
00133 printf(" specifies hue. (0.0 <-> 1.0) (for color camera only)\n");
00134 printf(" -whiteness=N\n");
00135 printf(" specifies whiteness. (0.0 <-> 1.0) (REMARK: gamma for some drivers, otherwise for greyscale camera only)\n");
00136 printf(" -color=N\n");
00137 printf(" specifies saturation (color). (0.0 <-> 1.0) (REMARK: obsolete !! use saturation control)\n\n");
00138 printf("OPTION CONTROLS:\n");
00139 printf(" -mode=[PAL|NTSC|SECAM]\n");
00140 printf(" specifies TV signal mode (for tv/capture card).\n");
00141 printf("\n");
00142
00143 return 0;
00144 }
00145
00146 AR2VideoParamT *ar2VideoOpen( char *config_in )
00147 {
00148 AR2VideoParamT *vid;
00149 struct video_capability vd;
00150 struct video_channel vc[MAXCHANNEL];
00151 struct video_picture vp;
00152 char *config, *a, line[256];
00153 int i;
00154 int adjust = 1;
00155
00156
00157
00158 if (!config_in || !(config_in[0])) {
00159
00160 char *envconf = getenv ("ARTOOLKIT_CONFIG");
00161 if (envconf && envconf[0]) {
00162 config = envconf;
00163 printf ("Using config string from environment [%s].\n", envconf);
00164 } else {
00165 config = NULL;
00166 printf ("No video config string supplied, using defaults.\n");
00167 }
00168 } else {
00169 config = config_in;
00170 printf ("Using supplied video config string [%s].\n", config_in);
00171 }
00172
00173 arMalloc( vid, AR2VideoParamT, 1 );
00174 strcpy( vid->dev, DEFAULT_VIDEO_DEVICE );
00175 vid->channel = DEFAULT_VIDEO_CHANNEL;
00176 vid->width = DEFAULT_VIDEO_WIDTH;
00177 vid->height = DEFAULT_VIDEO_HEIGHT;
00178 #if (AR_DEFAULT_PIXEL_FORMAT == AR_PIXEL_FORMAT_BGRA)
00179 vid->palette = VIDEO_PALETTE_RGB32;
00180 #elif (AR_DEFAULT_PIXEL_FORMAT == AR_PIXEL_FORMAT_BGR) || (AR_DEFAULT_PIXEL_FORMAT == AR_PIXEL_FORMAT_RGB)
00181 vid->palette = VIDEO_PALETTE_RGB24;
00182 #endif
00183 vid->contrast = -1.;
00184 vid->brightness = -1.;
00185 vid->saturation = -1.;
00186 vid->hue = -1.;
00187 vid->whiteness = -1.;
00188 vid->mode = DEFAULT_VIDEO_MODE;
00189 vid->debug = 0;
00190 vid->videoBuffer=NULL;
00191
00192 a = config;
00193 if( a != NULL) {
00194 for(;;) {
00195 while( *a == ' ' || *a == '\t' ) a++;
00196 if( *a == '\0' ) break;
00197 if( strncmp( a, "-dev=", 5 ) == 0 ) {
00198 sscanf( a, "%s", line );
00199 if( sscanf( &line[5], "%s", vid->dev ) == 0 ) {
00200 ar2VideoDispOption();
00201 free( vid );
00202 return 0;
00203 }
00204 }
00205 else if( strncmp( a, "-channel=", 9 ) == 0 ) {
00206 sscanf( a, "%s", line );
00207 if( sscanf( &line[9], "%d", &vid->channel ) == 0 ) {
00208 ar2VideoDispOption();
00209 free( vid );
00210 return 0;
00211 }
00212 }
00213 else if( strncmp( a, "-width=", 7 ) == 0 ) {
00214 sscanf( a, "%s", line );
00215 if( sscanf( &line[7], "%d", &vid->width ) == 0 ) {
00216 ar2VideoDispOption();
00217 free( vid );
00218 return 0;
00219 }
00220 }
00221 else if( strncmp( a, "-height=", 8 ) == 0 ) {
00222 sscanf( a, "%s", line );
00223 if( sscanf( &line[8], "%d", &vid->height ) == 0 ) {
00224 ar2VideoDispOption();
00225 free( vid );
00226 return 0;
00227 }
00228 }
00229 else if( strncmp( a, "-palette=", 9 ) == 0 ) {
00230 if( strncmp( &a[9], "RGB", 3) == 0 ) {
00231 #if (AR_DEFAULT_PIXEL_FORMAT == AR_PIXEL_FORMAT_BGRA)
00232 vid->palette = VIDEO_PALETTE_RGB32;
00233 #elif (AR_DEFAULT_PIXEL_FORMAT == AR_PIXEL_FORMAT_BGR)|| (AR_DEFAULT_PIXEL_FORMAT == AR_PIXEL_FORMAT_RGB)
00234 vid->palette = VIDEO_PALETTE_RGB24;
00235 #endif
00236 }
00237 else if( strncmp( &a[9], "YUV420P", 7 ) == 0 ) {
00238 vid->palette = VIDEO_PALETTE_YUV420P;
00239 }
00240 }
00241 else if( strncmp ( a, "-noadjust", 9 ) == 0 ) {
00242 adjust = 0;
00243 }
00244 else if( strncmp( a, "-contrast=", 10 ) == 0 ) {
00245 sscanf( a, "%s", line );
00246 if( sscanf( &line[10], "%lf", &vid->contrast ) == 0 ) {
00247 ar2VideoDispOption();
00248 free( vid );
00249 return 0;
00250 }
00251 }
00252 else if( strncmp( a, "-brightness=", 12 ) == 0 ) {
00253 sscanf( a, "%s", line );
00254 if( sscanf( &line[12], "%lf", &vid->brightness ) == 0 ) {
00255 ar2VideoDispOption();
00256 free( vid );
00257 return 0;
00258 }
00259 }
00260 else if( strncmp( a, "-saturation=", 12 ) == 0 ) {
00261 sscanf( a, "%s", line );
00262 if( sscanf( &line[12], "%lf", &vid->saturation ) == 0 ) {
00263 ar2VideoDispOption();
00264 free( vid );
00265 return 0;
00266 }
00267 }
00268 else if( strncmp( a, "-hue=", 5 ) == 0 ) {
00269 sscanf( a, "%s", line );
00270 if( sscanf( &line[5], "%lf", &vid->hue ) == 0 ) {
00271 ar2VideoDispOption();
00272 free( vid );
00273 return 0;
00274 }
00275 }
00276 else if( strncmp( a, "-whiteness=", 11 ) == 0 ) {
00277 sscanf( a, "%s", line );
00278 if( sscanf( &line[11], "%lf", &vid->whiteness ) == 0 ) {
00279 ar2VideoDispOption();
00280 free( vid );
00281 return 0;
00282 }
00283 }
00284 else if( strncmp( a, "-color=", 7 ) == 0 ) {
00285 sscanf( a, "%s", line );
00286 if( sscanf( &line[7], "%lf", &vid->saturation ) == 0 ) {
00287 ar2VideoDispOption();
00288 free( vid );
00289 return 0;
00290 }
00291 }
00292 else if( strncmp( a, "-mode=", 6 ) == 0 ) {
00293 if( strncmp( &a[6], "PAL", 3 ) == 0 ) vid->mode = VIDEO_MODE_PAL;
00294 else if( strncmp( &a[6], "NTSC", 4 ) == 0 ) vid->mode = VIDEO_MODE_NTSC;
00295 else if( strncmp( &a[6], "SECAM", 5 ) == 0 ) vid->mode = VIDEO_MODE_SECAM;
00296 else {
00297 ar2VideoDispOption();
00298 free( vid );
00299 return 0;
00300 }
00301 }
00302 else if( strncmp( a, "-debug", 6 ) == 0 ) {
00303 vid->debug = 1;
00304 }
00305 else {
00306 ar2VideoDispOption();
00307 free( vid );
00308 return 0;
00309 }
00310
00311 while( *a != ' ' && *a != '\t' && *a != '\0') a++;
00312 }
00313 }
00314
00315 vid->fd = open(vid->dev, O_RDWR);
00316 if(vid->fd < 0){
00317 printf("video device (%s) open failed\n",vid->dev);
00318 free( vid );
00319 return 0;
00320 }
00321
00322 if(ioctl(vid->fd,VIDIOCGCAP,&vd) < 0){
00323 printf("ioctl failed\n");
00324 free( vid );
00325 return 0;
00326 }
00327
00328 if( vid->debug ) {
00329 printf("=== debug info ===\n");
00330 printf(" vd.name = %s\n",vd.name);
00331 printf(" vd.channels = %d\n",vd.channels);
00332 printf(" vd.maxwidth = %d\n",vd.maxwidth);
00333 printf(" vd.maxheight = %d\n",vd.maxheight);
00334 printf(" vd.minwidth = %d\n",vd.minwidth);
00335 printf(" vd.minheight = %d\n",vd.minheight);
00336 }
00337
00338
00339 if (adjust)
00340 {
00341 if (vid->width >= vd.maxwidth)
00342 vid->width = vd.maxwidth;
00343 if (vid->height >= vd.maxheight)
00344 vid->height = vd.maxheight;
00345 if (vid->debug)
00346 printf ("arVideoOpen: width/height adjusted to (%d, %d)\n", vid->width, vid->height);
00347 }
00348
00349
00350 if(vd.maxwidth < vid->width || vid->width < vd.minwidth ||
00351 vd.maxheight < vid->height || vid->height < vd.minheight ) {
00352 printf("arVideoOpen: width or height oversize \n");
00353 free( vid );
00354 return 0;
00355 }
00356
00357
00358 if (adjust)
00359 {
00360 if (vid->channel >= vd.channels)
00361 vid->channel = 0;
00362 if (vid->debug)
00363 printf ("arVideoOpen: channel adjusted to 0\n");
00364 }
00365
00366
00367 if(vid->channel < 0 || vid->channel >= vd.channels){
00368 printf("arVideoOpen: channel# is not valid. \n");
00369 free( vid );
00370 return 0;
00371 }
00372
00373 if( vid->debug ) {
00374 printf("==== capture device channel info ===\n");
00375 }
00376
00377 for(i = 0;i < vd.channels && i < MAXCHANNEL; i++){
00378 vc[i].channel = i;
00379 if(ioctl(vid->fd,VIDIOCGCHAN,&vc[i]) < 0){
00380 printf("error: acquireing channel(%d) info\n",i);
00381 free( vid );
00382 return 0;
00383 }
00384
00385 if( vid->debug ) {
00386 printf(" channel = %d\n", vc[i].channel);
00387 printf(" name = %s\n", vc[i].name);
00388 printf(" tuners = %d", vc[i].tuners);
00389
00390 printf(" flag = 0x%08x",vc[i].flags);
00391 if(vc[i].flags & VIDEO_VC_TUNER)
00392 printf(" TUNER");
00393 if(vc[i].flags & VIDEO_VC_AUDIO)
00394 printf(" AUDIO");
00395 printf("\n");
00396
00397 printf(" vc[%d].type = 0x%08x", i, vc[i].type);
00398 if(vc[i].type & VIDEO_TYPE_TV)
00399 printf(" TV");
00400 if(vc[i].type & VIDEO_TYPE_CAMERA)
00401 printf(" CAMERA");
00402 printf("\n");
00403 }
00404 }
00405
00406
00407 vc[vid->channel].norm = vid->mode;
00408 if(ioctl(vid->fd, VIDIOCSCHAN, &vc[vid->channel]) < 0){
00409 printf("error: selecting channel %d\n", vid->channel);
00410 free( vid );
00411 return 0;
00412 }
00413
00414 if(ioctl(vid->fd, VIDIOCGPICT, &vp)) {
00415 printf("error: getting palette\n");
00416 free( vid );
00417 return 0;
00418 }
00419
00420 if( vid->debug ) {
00421 printf("=== debug info ===\n");
00422 printf(" vp.brightness= %d\n",vp.brightness);
00423 printf(" vp.hue = %d\n",vp.hue);
00424 printf(" vp.colour = %d\n",vp.colour);
00425 printf(" vp.contrast = %d\n",vp.contrast);
00426 printf(" vp.whiteness = %d\n",vp.whiteness);
00427 printf(" vp.depth = %d\n",vp.depth);
00428 printf(" vp.palette = %d\n",vp.palette);
00429 }
00430
00431
00432 if ((vid->brightness+1.)>0.001)
00433 vp.brightness = 32767 * 2.0 *vid->brightness;
00434 if ((vid->contrast+1.)>0.001)
00435 vp.contrast = 32767 * 2.0 *vid->contrast;
00436 if ((vid->hue+1.)>0.001)
00437 vp.hue = 32767 * 2.0 *vid->hue;
00438 if ((vid->whiteness+1.)>0.001)
00439 vp.whiteness = 32767 * 2.0 *vid->whiteness;
00440 if ((vid->saturation+1.)>0.001)
00441 vp.colour = 32767 * 2.0 *vid->saturation;
00442 vp.depth = 24;
00443 vp.palette = vid->palette;
00444
00445 if(ioctl(vid->fd, VIDIOCSPICT, &vp)) {
00446 printf("error: setting configuration !! bad palette mode..\n TIPS:try other palette mode (or with new failure contact ARToolKit Developer)\n");
00447 free( vid );
00448 return 0;
00449 }
00450 if (vid->palette==VIDEO_PALETTE_YUV420P)
00451 arMalloc( vid->videoBuffer, ARUint8, vid->width*vid->height*3 );
00452
00453 if( vid->debug ) {
00454 if(ioctl(vid->fd, VIDIOCGPICT, &vp)) {
00455 printf("error: getting palette\n");
00456 free( vid );
00457 return 0;
00458 }
00459 printf("=== debug info ===\n");
00460 printf(" vp.brightness= %d\n",vp.brightness);
00461 printf(" vp.hue = %d\n",vp.hue);
00462 printf(" vp.colour = %d\n",vp.colour);
00463 printf(" vp.contrast = %d\n",vp.contrast);
00464 printf(" vp.whiteness = %d\n",vp.whiteness);
00465 printf(" vp.depth = %d\n",vp.depth);
00466 printf(" vp.palette = %d\n",vp.palette);
00467 }
00468
00469
00470 if(ioctl(vid->fd,VIDIOCGMBUF,&vid->vm) < 0){
00471 printf("error: videocgmbuf\n");
00472 free( vid );
00473 return 0;
00474 }
00475
00476 if( vid->debug ) {
00477 printf("===== Image Buffer Info =====\n");
00478 printf(" size = %d[bytes]\n", vid->vm.size);
00479 printf(" frames = %d\n", vid->vm.frames);
00480 }
00481 if(vid->vm.frames < 2){
00482 printf("this device can not be supported by libARvideo.\n");
00483 printf("(vm.frames < 2)\n");
00484 free( vid );
00485 return 0;
00486 }
00487
00488
00489
00490 if((vid->map = (ARUint8 *)mmap(0, vid->vm.size, PROT_READ|PROT_WRITE, MAP_SHARED, vid->fd, 0)) < 0){
00491 printf("error: mmap\n");
00492 free( vid );
00493 return 0;
00494 }
00495
00496
00497 vid->vmm.frame = 0;
00498 vid->vmm.width = vid->width;
00499 vid->vmm.height = vid->height;
00500 vid->vmm.format= vid->palette;
00501
00502 vid->video_cont_num = -1;
00503
00504 #ifdef USE_EYETOY
00505 JPEGToRGBInit(vid->width,vid->height);
00506 #endif
00507 return vid;
00508 }
00509
00510 int ar2VideoClose( AR2VideoParamT *vid )
00511 {
00512 if(vid->video_cont_num >= 0){
00513 ar2VideoCapStop( vid );
00514 }
00515 close(vid->fd);
00516 if(vid->videoBuffer!=NULL)
00517 free(vid->videoBuffer);
00518 free( vid );
00519
00520 return 0;
00521 }
00522
00523
00524 int ar2VideoCapStart( AR2VideoParamT *vid )
00525 {
00526 if(vid->video_cont_num >= 0){
00527 printf("arVideoCapStart has already been called.\n");
00528 return -1;
00529 }
00530
00531 vid->video_cont_num = 0;
00532 vid->vmm.frame = vid->video_cont_num;
00533 if(ioctl(vid->fd, VIDIOCMCAPTURE, &vid->vmm) < 0) {
00534 return -1;
00535 }
00536 vid->vmm.frame = 1 - vid->vmm.frame;
00537 if( ioctl(vid->fd, VIDIOCMCAPTURE, &vid->vmm) < 0) {
00538 return -1;
00539 }
00540
00541 return 0;
00542 }
00543
00544 int ar2VideoCapNext( AR2VideoParamT *vid )
00545 {
00546 if(vid->video_cont_num < 0){
00547 printf("arVideoCapStart has never been called.\n");
00548 return -1;
00549 }
00550
00551 vid->vmm.frame = 1 - vid->vmm.frame;
00552 ioctl(vid->fd, VIDIOCMCAPTURE, &vid->vmm);
00553
00554 return 0;
00555 }
00556
00557 int ar2VideoCapStop( AR2VideoParamT *vid )
00558 {
00559 if(vid->video_cont_num < 0){
00560 printf("arVideoCapStart has never been called.\n");
00561 return -1;
00562 }
00563 if(ioctl(vid->fd, VIDIOCSYNC, &vid->video_cont_num) < 0){
00564 printf("error: videosync\n");
00565 return -1;
00566 }
00567 vid->video_cont_num = -1;
00568
00569 return 0;
00570 }
00571
00572
00573 ARUint8 *ar2VideoGetImage( AR2VideoParamT *vid )
00574 {
00575 ARUint8 *buf;
00576
00577 if(vid->video_cont_num < 0){
00578 printf("arVideoCapStart has never been called.\n");
00579 return NULL;
00580 }
00581
00582 if(ioctl(vid->fd, VIDIOCSYNC, &vid->video_cont_num) < 0){
00583 printf("error: videosync\n");
00584 return NULL;
00585 }
00586 vid->video_cont_num = 1 - vid->video_cont_num;
00587
00588 if(vid->video_cont_num == 0)
00589 buf=(vid->map + vid->vm.offsets[1]);
00590 else
00591 buf=(vid->map + vid->vm.offsets[0]);
00592
00593 if(vid->palette == VIDEO_PALETTE_YUV420P)
00594 {
00595
00596
00597
00598
00599
00600
00601 ccvt_420p_bgr24(vid->width, vid->height, buf, vid->videoBuffer);
00602
00603 return vid->videoBuffer;
00604 }
00605 #ifdef USE_EYETOY
00606 buf=JPEGToRGB(buf,vid->width, vid->height);
00607 #endif
00608
00609 return buf;
00610
00611 }
00612
00613 int ar2VideoInqSize(AR2VideoParamT *vid, int *x,int *y)
00614 {
00615 *x = vid->vmm.width;
00616 *y = vid->vmm.height;
00617
00618 return 0;
00619 }