00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <iostream>
00022
00023 #include <sys/ioctl.h>
00024 #include <sys/types.h>
00025 #include <sys/stat.h>
00026 #include <fcntl.h>
00027 #include <unistd.h>
00028 #include <stdio.h>
00029 #include <errno.h>
00030 #include <sys/mman.h>
00031 #include <string.h>
00032
00033 #include "ccvt.h"
00034 #include "pwc-ioctl.h"
00035 #include "v4l1_pwc.h"
00036 #include "../eventloop.h"
00037
00038 #define ERRMSG_SIZ 1024
00039
00040 extern int errno;
00041 using namespace std;
00042
00043 V4L1_PWC::V4L1_PWC()
00044 {
00045 frameRate=15;
00046 fd=-1;
00047 streamActive = true;
00048
00049 YBuf = NULL;
00050 UBuf = NULL;
00051 VBuf = NULL;
00052 colorBuffer= NULL;
00053 buffer_start=NULL;
00054 }
00055
00056 V4L1_PWC::~V4L1_PWC()
00057 {
00058
00059 }
00060
00061 int V4L1_PWC::connectCam(const char * devpath, char *errmsg)
00062 {
00063 options= (ioNoBlock|ioUseSelect|haveBrightness|haveContrast|haveColor);
00064 struct pwc_probe probe;
00065 bool IsPhilips = false;
00066 frameRate=15;
00067 fd=-1;
00068 streamActive = true;
00069 buffer_start=NULL;
00070
00071 if (-1 == (fd=open(devpath,
00072 O_RDONLY | ((options & ioNoBlock) ? O_NONBLOCK : 0)))) {
00073
00074 strncpy(errmsg, strerror(errno), 1024);
00075 cerr << strerror(errno);
00076 return -1;
00077 }
00078
00079 cerr << "Device opened" << endl;
00080
00081 if (fd != -1) {
00082 if (-1 == ioctl(fd,VIDIOCGCAP,&capability)) {
00083 cerr << "Error: ioctl (VIDIOCGCAP)" << endl;
00084 strncpy(errmsg, "ioctl (VIDIOCGCAP)", 1024);
00085 return -1;
00086 }
00087 if (-1 == ioctl (fd, VIDIOCGWIN, &window)) {
00088 cerr << "Error: ioctl (VIDIOCGWIN)" << endl;
00089 strncpy(errmsg, "ioctl (VIDIOCGWIN)", 1024);
00090 return -1;
00091 }
00092 if (-1 == ioctl (fd, VIDIOCGPICT, &picture_format)) {
00093 cerr << "Error: ioctl (VIDIOCGPICT)" << endl;
00094 strncpy(errmsg, "ioctl (VIDIOCGPICT)", 1024);
00095 return -1;
00096 }
00097 init(0);
00098 }
00099
00100
00101 if (ioctl(fd, VIDIOCPWCPROBE, &probe) == 0)
00102 {
00103 if (!strcmp(capability.name,probe.name))
00104 {
00105 IsPhilips = true;
00106 type_=probe.type;
00107 }
00108 }
00109
00110 if (IsPhilips)
00111 cerr << "Philips webcam type " << type_ << " detected" << endl;
00112 else
00113 {
00114 strncpy(errmsg, "No Philips webcam detected.", 1024);
00115 return -1;
00116 }
00117
00118 cerr << "initial size w:" << window.width << " -- h: " << window.height << endl;
00119
00120
00121 mmapInit();
00122
00123 setWhiteBalanceMode(PWC_WB_AUTO, errmsg);
00124 multiplicateur_=1;
00125 skippedFrame_=0;
00126 lastGain_=getGain();
00127
00128 cerr << "All successful, returning\n";
00129 return fd;
00130 }
00131
00132 void V4L1_PWC::checkSize(int & x, int & y)
00133 {
00134 if (x>=capability.maxwidth && y >= capability.maxheight)
00135 {
00136 x=capability.maxwidth;
00137 y=capability.maxheight;
00138 } else if (x>=352 && y >=288 && type_<700) {
00139 x=352;y=288;
00140 } else if (x>=320 && y >= 240) {
00141 x=320;y=240;
00142 } else if (x>=176 && y >=144 && type_<700 ) {
00143 x=176;y=144;
00144 } else if (x>=160 && y >=120 ) {
00145 x=160;y=120;
00146 } else {
00147 x=capability.minwidth;
00148 y=capability.minheight;
00149 }
00150 }
00151
00152 bool V4L1_PWC::setSize(int x, int y)
00153 {
00154
00155 int oldX, oldY;
00156 char msg[ERRMSG_SIZ];
00157 checkSize(x,y);
00158
00159 oldX = window.width;
00160 oldY = window.height;
00161
00162 window.width=x;
00163 window.height=y;
00164
00165 if (ioctl (fd, VIDIOCSWIN, &window))
00166 {
00167 snprintf(msg, ERRMSG_SIZ, "ioctl(VIDIOCSWIN) %s", strerror(errno));
00168 cerr << msg << endl;
00169 window.width=oldX;
00170 window.height=oldY;
00171 return false;
00172 }
00173 ioctl (fd, VIDIOCGWIN, &window);
00174
00175 cerr << "New size is x=" << window.width << " " << "y=" << window.height <<endl;
00176
00177 allocBuffers();
00178
00179 return true;
00180 }
00181
00182 int V4L1_PWC::saveSettings(char *errmsg)
00183 {
00184 if (ioctl(fd, VIDIOCPWCSUSER)==-1)
00185 {
00186 snprintf(errmsg, ERRMSG_SIZ, "VIDIOCPWCSUSER %s", strerror(errno));
00187 return -1;
00188 }
00189
00190 return 0;
00191 }
00192
00193 void V4L1_PWC::restoreSettings()
00194 {
00195 ioctl(fd, VIDIOCPWCRUSER);
00196 getPictureSettings();
00197 }
00198
00199 void V4L1_PWC::restoreFactorySettings()
00200 {
00201 ioctl(fd, VIDIOCPWCFACTORY);
00202 getPictureSettings();
00203 }
00204
00205 int V4L1_PWC::setGain(int val, char *errmsg)
00206 {
00207 if(-1==ioctl(fd, VIDIOCPWCSAGC, &val))
00208 {
00209 snprintf(errmsg, ERRMSG_SIZ, "VIDIOCPWCSAGC %s", strerror(errno));
00210 return -1;
00211 }
00212 else lastGain_=val;
00213
00214 cerr << "setGain "<<val<<endl;
00215
00216 return lastGain_;
00217 }
00218
00219 int V4L1_PWC::getGain()
00220 {
00221 int gain;
00222 char msg[ERRMSG_SIZ];
00223 static int cpt=0;
00224 if ((cpt%4)==0)
00225 {
00226 if (-1==ioctl(fd, VIDIOCPWCGAGC, &gain))
00227 {
00228
00229 snprintf(msg, ERRMSG_SIZ, "VIDIOCPWCGAGC %s", strerror(errno));
00230 cerr << msg << endl;
00231 gain=lastGain_;
00232 } else
00233 {
00234 ++cpt;
00235 lastGain_=gain;
00236 }
00237 } else
00238 {
00239 ++cpt;
00240 gain=lastGain_;
00241 }
00242
00243 if (gain < 0) gain*=-1;
00244 return gain;
00245 }
00246
00247 int V4L1_PWC::setExposure(int val, char *errmsg)
00248 {
00249
00250
00251 if (-1==ioctl(fd, VIDIOCPWCSSHUTTER, &val))
00252 {
00253 snprintf(errmsg, ERRMSG_SIZ, "VIDIOCPWCSSHUTTER %s", strerror(errno));
00254 return -1;
00255 }
00256
00257 return 0;
00258 }
00259
00260 void V4L1_PWC::setCompression(int val)
00261 {
00262 ioctl(fd, VIDIOCPWCSCQUAL, &val);
00263 }
00264
00265 int V4L1_PWC::getCompression()
00266 {
00267 int gain;
00268 ioctl(fd, VIDIOCPWCGCQUAL , &gain);
00269 if (gain < 0) gain*=-1;
00270 return gain;
00271 }
00272
00273 int V4L1_PWC::setNoiseRemoval(int val, char *errmsg)
00274 {
00275 if (-1 == ioctl(fd, VIDIOCPWCSDYNNOISE, &val))
00276 {
00277 snprintf(errmsg, ERRMSG_SIZ, "VIDIOCPWCGDYNNOISE %s", strerror(errno));
00278 return -1;
00279 }
00280
00281 return 0;
00282 }
00283
00284 int V4L1_PWC::getNoiseRemoval()
00285 {
00286 int gain;
00287 char msg[ERRMSG_SIZ];
00288
00289 if (-1 == ioctl(fd, VIDIOCPWCGDYNNOISE , &gain))
00290 {
00291 snprintf(msg, ERRMSG_SIZ, "VIDIOCPWCGDYNNOISE %s", strerror(errno));
00292 cerr << msg << endl;
00293 }
00294
00295 cout <<"get noise = "<<gain<<endl;
00296 return gain;
00297 }
00298
00299 int V4L1_PWC::setSharpness(int val, char *errmsg)
00300 {
00301 if (-1 == ioctl(fd, VIDIOCPWCSCONTOUR, &val))
00302 {
00303 snprintf(errmsg, ERRMSG_SIZ, "VIDIOCPWCSCONTOUR %s", strerror(errno));
00304 return -1;
00305 }
00306
00307 return 0;
00308 }
00309
00310 int V4L1_PWC::getSharpness()
00311 {
00312 int gain;
00313 char msg[ERRMSG_SIZ];
00314
00315 if (-1 == ioctl(fd, VIDIOCPWCGCONTOUR, &gain))
00316 {
00317 snprintf(msg, ERRMSG_SIZ, "VIDIOCPWCGCONTOUR %s", strerror(errno));
00318 cerr << msg << endl;
00319 }
00320
00321 cout <<"get sharpness = "<<gain<<endl;
00322 return gain;
00323 }
00324
00325 int V4L1_PWC::setBackLight(bool val, char *errmsg)
00326 {
00327 static int on=1;
00328 static int off=0;
00329 if (-1 == ioctl(fd,VIDIOCPWCSBACKLIGHT, & val?&on:&off))
00330 {
00331 snprintf(errmsg, ERRMSG_SIZ, "VIDIOCPWCSBACKLIGHT %s", strerror(errno));
00332 return -1;
00333 }
00334
00335 return 0;
00336 }
00337
00338 bool V4L1_PWC::getBackLight()
00339 {
00340 int val;
00341 char msg[ERRMSG_SIZ];
00342
00343 if (-1 == ioctl(fd,VIDIOCPWCGBACKLIGHT, & val))
00344 {
00345 snprintf(msg, ERRMSG_SIZ, "VIDIOCPWCSBACKLIGHT %s", strerror(errno));
00346 cerr << msg << endl;
00347 }
00348
00349 return val !=0;
00350 }
00351
00352 int V4L1_PWC::setFlicker(bool val, char *errmsg)
00353 {
00354 static int on=1;
00355 static int off=0;
00356 if (-1 == ioctl(fd,VIDIOCPWCSFLICKER, val?&on:&off))
00357 {
00358 snprintf(errmsg, ERRMSG_SIZ, "VIDIOCPWCSFLICKER %s", strerror(errno));
00359 return -1;
00360 }
00361
00362 return 0;
00363
00364 }
00365
00366 bool V4L1_PWC::getFlicker()
00367 {
00368 int val;
00369 char msg[ERRMSG_SIZ];
00370
00371 if (-1 == ioctl(fd,VIDIOCPWCGFLICKER, & val))
00372 {
00373 snprintf(msg, ERRMSG_SIZ, "VIDIOCPWCGFLICKER %s", strerror(errno));
00374 cerr << msg << endl;
00375 }
00376
00377 return val !=0;
00378 }
00379
00380 void V4L1_PWC::setGama(int val)
00381 {
00382 picture_format.whiteness=val;
00383 setPictureSettings();
00384 }
00385
00386 int V4L1_PWC::getGama()
00387 {
00388 return picture_format.whiteness;
00389 }
00390
00391 int V4L1_PWC::setFrameRate(int value, char *errmsg)
00392 {
00393 window.flags = (window.flags & ~PWC_FPS_MASK) | ((value << PWC_FPS_SHIFT) & PWC_FPS_MASK);
00394 if (ioctl(fd, VIDIOCSWIN, &window))
00395 {
00396 snprintf(errmsg, ERRMSG_SIZ, "setFrameRate %s", strerror(errno));
00397 return -1;
00398 }
00399
00400 ioctl(fd, VIDIOCGWIN, &window);
00401 frameRate = value;
00402
00403 return 0;
00404
00405 }
00406
00407 int V4L1_PWC::getFrameRate()
00408 {
00409 return ((window.flags&PWC_FPS_FRMASK)>>PWC_FPS_SHIFT);
00410 }
00411
00412 int V4L1_PWC::getWhiteBalance()
00413 {
00414 char msg[ERRMSG_SIZ];
00415 struct pwc_whitebalance tmp_whitebalance;
00416 tmp_whitebalance.mode = tmp_whitebalance.manual_red = tmp_whitebalance.manual_blue = tmp_whitebalance.read_red = tmp_whitebalance.read_blue = PWC_WB_AUTO;
00417
00418 if (ioctl(fd, VIDIOCPWCGAWB, &tmp_whitebalance))
00419 {
00420 snprintf(msg, ERRMSG_SIZ, "getWhiteBalance %s", strerror(errno));
00421 cerr << msg << endl;
00422 }
00423 else
00424 {
00425 #if 0
00426 cout << "mode="<<tmp_whitebalance.mode
00427 <<" mr="<<tmp_whitebalance.manual_red
00428 <<" mb="<<tmp_whitebalance.manual_blue
00429 <<" ar="<<tmp_whitebalance.read_red
00430 <<" ab="<<tmp_whitebalance.read_blue
00431 <<endl;
00432 #endif
00433
00434 whiteBalanceMode_=tmp_whitebalance.mode;
00435 }
00436
00437 return whiteBalanceMode_;
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483 }
00484
00485 int V4L1_PWC::setWhiteBalance(char *errmsg)
00486 {
00487 struct pwc_whitebalance wb;
00488 wb.mode=whiteBalanceMode_;
00489 if (wb.mode == PWC_WB_MANUAL)
00490 {
00491 wb.manual_red=whiteBalanceRed_;
00492 wb.manual_blue=whiteBalanceBlue_;
00493 }
00494
00495 if (ioctl(fd, VIDIOCPWCSAWB, &wb))
00496 {
00497 snprintf(errmsg, ERRMSG_SIZ, "setWhiteBalance %s", strerror(errno));
00498 return -1;
00499 }
00500
00501 return 0;
00502 }
00503
00504 int V4L1_PWC::setWhiteBalanceMode(int val, char *errmsg)
00505 {
00506 if (val == whiteBalanceMode_)
00507 return whiteBalanceMode_;
00508
00509 if (val != PWC_WB_AUTO)
00510 {
00511 if ( val != PWC_WB_MANUAL)
00512 {
00513 whiteBalanceMode_=val;
00514 if (setWhiteBalance(errmsg) < 0)
00515 return -1;
00516 }
00517
00518
00519 whiteBalanceMode_= val;
00520 if (setWhiteBalance(errmsg) < 0)
00521 return -1;
00522 getWhiteBalance();
00523 }
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536 whiteBalanceMode_=val;
00537 if (setWhiteBalance(errmsg) < 0)
00538 return -1;
00539 getWhiteBalance();
00540
00541 return 0;
00542 }
00543
00544 int V4L1_PWC::setWhiteBalanceRed(int val, char *errmsg)
00545 {
00546 whiteBalanceMode_ = PWC_WB_MANUAL;
00547 whiteBalanceRed_=val;
00548 if (setWhiteBalance(errmsg) < 0)
00549 return -1;
00550
00551 return 0;
00552 }
00553
00554 int V4L1_PWC::setWhiteBalanceBlue(int val, char *errmsg)
00555 {
00556 whiteBalanceMode_ = PWC_WB_MANUAL;
00557 whiteBalanceBlue_=val;
00558 if (setWhiteBalance(errmsg) < 0)
00559 return -1;
00560
00561 return 0;
00562 }
00563