source: BAORadio/libindi/v1.0.1/libs/webcam/v4l1_pwc.cpp @ 614

Last change on this file since 614 was 490, checked in by campagne, 14 years ago

import libindi (JEC)

File size: 12.5 KB
Line 
1/*
2    Phlips webcam driver for V4L 1
3    Copyright (C) 2005 by Jasem Mutlaq <mutlaqja@ikarustech.com>
4
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with this library; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18
19*/
20
21#include <iostream>
22
23#include <sys/ioctl.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <fcntl.h>
27#include <unistd.h>
28#include <stdio.h>
29#include <errno.h>
30#include <sys/mman.h>
31#include <string.h>
32
33#include "ccvt.h"
34#include "pwc-ioctl.h"
35#include "v4l1_pwc.h"
36#include "../eventloop.h"
37
38#define ERRMSG_SIZ      1024
39
40extern int errno;
41using namespace std;
42
43V4L1_PWC::V4L1_PWC()
44{
45   frameRate=15;
46   fd=-1;
47   streamActive = true;
48
49   YBuf       = NULL;
50   UBuf       = NULL;
51   VBuf       = NULL;
52   colorBuffer= NULL;
53   buffer_start=NULL;
54}
55
56V4L1_PWC::~V4L1_PWC()
57{
58
59} 
60
61int V4L1_PWC::connectCam(const char * devpath, char *errmsg)
62{
63   options= (ioNoBlock|ioUseSelect|haveBrightness|haveContrast|haveColor);
64   struct pwc_probe probe;
65   bool IsPhilips = false;
66   frameRate=15;
67   fd=-1;
68   streamActive = true;
69   buffer_start=NULL;
70   
71   if (-1 == (fd=open(devpath,
72                           O_RDONLY | ((options & ioNoBlock) ? O_NONBLOCK : 0)))) {
73     
74      strncpy(errmsg, strerror(errno), 1024);
75      cerr << strerror(errno);
76      return -1;
77   } 
78 
79   cerr << "Device opened" << endl;
80   
81   if (fd != -1) {
82      if (-1 == ioctl(fd,VIDIOCGCAP,&capability)) {
83         cerr << "Error: ioctl (VIDIOCGCAP)" << endl;
84         strncpy(errmsg, "ioctl (VIDIOCGCAP)", 1024);
85         return -1;
86      }
87      if (-1 == ioctl (fd, VIDIOCGWIN, &window)) {
88         cerr << "Error: ioctl (VIDIOCGWIN)" << endl;
89         strncpy(errmsg, "ioctl (VIDIOCGWIN)", 1024);
90         return -1;
91      }
92      if (-1 == ioctl (fd, VIDIOCGPICT, &picture_format)) {
93         cerr << "Error: ioctl (VIDIOCGPICT)" << endl;
94         strncpy(errmsg, "ioctl (VIDIOCGPICT)", 1024);
95         return -1;
96      }
97      init(0);
98   }
99   
100  // Check to see if it's really a philips webcam       
101  if (ioctl(fd, VIDIOCPWCPROBE, &probe) == 0) 
102  {
103            if (!strcmp(capability.name,probe.name))
104            {
105               IsPhilips = true;
106               type_=probe.type;
107            }
108 }
109         
110  if (IsPhilips)
111      cerr << "Philips webcam type " << type_ << " detected" << endl;
112  else
113  {
114   strncpy(errmsg, "No Philips webcam detected.", 1024);
115   return -1;
116  }
117   
118   cerr << "initial size w:" << window.width << " -- h: " << window.height << endl;
119   
120   
121   mmapInit();
122   
123   setWhiteBalanceMode(PWC_WB_AUTO, errmsg);
124   multiplicateur_=1;
125   skippedFrame_=0;
126   lastGain_=getGain();
127
128   cerr << "All successful, returning\n";
129   return fd;
130}
131
132void V4L1_PWC::checkSize(int & x, int & y) 
133{
134 if (x>=capability.maxwidth && y >= capability.maxheight)
135   {
136      x=capability.maxwidth;
137      y=capability.maxheight;
138   } else if (x>=352 && y >=288 && type_<700) {
139      x=352;y=288;
140   } else if (x>=320 && y >= 240) {
141      x=320;y=240;
142   } else if (x>=176 && y >=144 && type_<700 ) {
143      x=176;y=144;
144   } else if (x>=160 && y >=120 ) {
145      x=160;y=120;
146   } else {
147      x=capability.minwidth;
148      y=capability.minheight;
149   }
150}
151
152bool V4L1_PWC::setSize(int x, int y) 
153{
154
155   int oldX, oldY;
156   char msg[ERRMSG_SIZ];
157   checkSize(x,y);
158   
159   oldX = window.width;
160   oldY = window.height;
161   
162   window.width=x;
163   window.height=y;
164   
165   if (ioctl (fd, VIDIOCSWIN, &window))
166   {
167       snprintf(msg, ERRMSG_SIZ, "ioctl(VIDIOCSWIN) %s", strerror(errno));
168       cerr << msg << endl;
169       window.width=oldX;
170       window.height=oldY;
171       return false;
172   }
173   ioctl (fd, VIDIOCGWIN, &window);
174
175   cerr << "New size is x=" << window.width << " " << "y=" << window.height <<endl;
176   
177   allocBuffers();
178   
179   return true;
180}
181
182int V4L1_PWC::saveSettings(char *errmsg)
183{
184   if (ioctl(fd, VIDIOCPWCSUSER)==-1)
185    {
186      snprintf(errmsg, ERRMSG_SIZ, "VIDIOCPWCSUSER %s", strerror(errno));
187      return -1;
188   }
189   
190   return 0;
191}
192
193void V4L1_PWC::restoreSettings()
194 {
195   ioctl(fd, VIDIOCPWCRUSER);
196   getPictureSettings();
197}
198
199void V4L1_PWC::restoreFactorySettings()
200{
201   ioctl(fd, VIDIOCPWCFACTORY);
202   getPictureSettings();
203}
204
205int V4L1_PWC::setGain(int val, char *errmsg)
206 {
207   if(-1==ioctl(fd, VIDIOCPWCSAGC, &val))
208   {
209      snprintf(errmsg, ERRMSG_SIZ, "VIDIOCPWCSAGC %s", strerror(errno));
210      return -1;
211   }
212   else lastGain_=val;
213   
214   cerr << "setGain "<<val<<endl;
215   
216   return lastGain_;
217}
218
219int V4L1_PWC::getGain()
220{
221   int gain;
222   char msg[ERRMSG_SIZ];
223   static int cpt=0;
224   if ((cpt%4)==0)
225   {
226      if (-1==ioctl(fd, VIDIOCPWCGAGC, &gain))
227      {
228         //perror("VIDIOCPWCGAGC");
229         snprintf(msg, ERRMSG_SIZ, "VIDIOCPWCGAGC %s", strerror(errno));
230         cerr << msg << endl;
231         gain=lastGain_;
232      } else
233      {
234         ++cpt;
235         lastGain_=gain;
236      }
237   } else
238   {
239      ++cpt;
240      gain=lastGain_; 
241   }
242   //cerr << "get gain "<<gain<<endl;
243   if (gain < 0) gain*=-1;
244   return gain;
245}
246
247int V4L1_PWC::setExposure(int val, char *errmsg)
248 {
249   //cout << "set exposure "<<val<<"\n";
250   
251   if (-1==ioctl(fd, VIDIOCPWCSSHUTTER, &val))
252   {
253     snprintf(errmsg, ERRMSG_SIZ, "VIDIOCPWCSSHUTTER %s", strerror(errno));
254     return -1;
255  }
256 
257  return 0;
258}
259
260void V4L1_PWC::setCompression(int val)
261{
262   ioctl(fd, VIDIOCPWCSCQUAL, &val); 
263}
264
265int V4L1_PWC::getCompression()
266{
267   int gain;
268   ioctl(fd, VIDIOCPWCGCQUAL , &gain);
269   if (gain < 0) gain*=-1;
270   return gain;
271}
272
273int V4L1_PWC::setNoiseRemoval(int val, char *errmsg)
274{
275   if (-1 == ioctl(fd, VIDIOCPWCSDYNNOISE, &val))
276   {
277       snprintf(errmsg, ERRMSG_SIZ, "VIDIOCPWCGDYNNOISE %s", strerror(errno));
278       return -1;
279   }
280   
281   return 0;
282}
283
284int V4L1_PWC::getNoiseRemoval()
285{
286   int gain;
287   char msg[ERRMSG_SIZ];
288   
289   if (-1 == ioctl(fd, VIDIOCPWCGDYNNOISE , &gain)) 
290   {
291         snprintf(msg, ERRMSG_SIZ, "VIDIOCPWCGDYNNOISE %s", strerror(errno));
292         cerr << msg << endl;
293   }
294     
295   cout <<"get noise = "<<gain<<endl;
296   return gain;
297}
298
299int V4L1_PWC::setSharpness(int val, char *errmsg)
300 {
301   if (-1 == ioctl(fd, VIDIOCPWCSCONTOUR, &val))
302   {
303       snprintf(errmsg, ERRMSG_SIZ, "VIDIOCPWCSCONTOUR %s", strerror(errno));
304       return -1;
305  }
306 
307  return 0;
308}
309
310int V4L1_PWC::getSharpness()
311{
312   int gain;
313   char msg[ERRMSG_SIZ];
314   
315   if (-1 == ioctl(fd, VIDIOCPWCGCONTOUR, &gain)) 
316   {
317      snprintf(msg, ERRMSG_SIZ, "VIDIOCPWCGCONTOUR %s", strerror(errno));
318      cerr << msg << endl;
319  }
320   
321   cout <<"get sharpness = "<<gain<<endl;
322   return gain;
323}
324
325int V4L1_PWC::setBackLight(bool val, char *errmsg)
326{
327   static int on=1;
328   static int off=0;
329   if (-1 == ioctl(fd,VIDIOCPWCSBACKLIGHT, &  val?&on:&off))
330   {
331        snprintf(errmsg, ERRMSG_SIZ, "VIDIOCPWCSBACKLIGHT %s", strerror(errno));
332        return -1;
333   }
334   
335   return 0;
336}
337
338bool V4L1_PWC::getBackLight()
339{
340   int val;
341   char msg[ERRMSG_SIZ];
342   
343   if (-1 == ioctl(fd,VIDIOCPWCGBACKLIGHT, & val)) 
344   {
345      snprintf(msg, ERRMSG_SIZ, "VIDIOCPWCSBACKLIGHT %s", strerror(errno));
346      cerr << msg << endl;
347   }
348
349   return val !=0;
350}
351
352int V4L1_PWC::setFlicker(bool val, char *errmsg)
353{
354   static int on=1;
355   static int off=0;
356   if (-1 == ioctl(fd,VIDIOCPWCSFLICKER, val?&on:&off))
357   {
358      snprintf(errmsg, ERRMSG_SIZ, "VIDIOCPWCSFLICKER %s", strerror(errno));
359      return -1;
360   }
361   
362   return 0;
363   
364}
365
366bool V4L1_PWC::getFlicker() 
367{
368   int val;
369   char msg[ERRMSG_SIZ];
370   
371   if (-1 == ioctl(fd,VIDIOCPWCGFLICKER, & val))
372   {
373         snprintf(msg, ERRMSG_SIZ, "VIDIOCPWCGFLICKER %s", strerror(errno));
374         cerr << msg << endl;
375   }
376   
377   return val !=0;
378}
379
380void V4L1_PWC::setGama(int val)
381{
382   picture_format.whiteness=val;
383   setPictureSettings();
384}
385
386int V4L1_PWC::getGama() 
387{
388   return picture_format.whiteness;
389}
390
391int V4L1_PWC::setFrameRate(int value, char *errmsg)
392 {
393   window.flags = (window.flags & ~PWC_FPS_MASK) | ((value << PWC_FPS_SHIFT) & PWC_FPS_MASK);
394   if (ioctl(fd, VIDIOCSWIN, &window))
395   {
396             snprintf(errmsg, ERRMSG_SIZ, "setFrameRate %s", strerror(errno));
397             return -1;
398   }
399   
400   ioctl(fd, VIDIOCGWIN, &window);
401   frameRate = value;
402   
403   return 0;
404   //emit exposureTime(multiplicateur_/(double)getFrameRate());
405}
406
407int V4L1_PWC::getFrameRate() 
408{
409   return ((window.flags&PWC_FPS_FRMASK)>>PWC_FPS_SHIFT); 
410}
411
412int V4L1_PWC::getWhiteBalance()
413{
414   char msg[ERRMSG_SIZ];
415   struct pwc_whitebalance tmp_whitebalance;
416   tmp_whitebalance.mode = tmp_whitebalance.manual_red = tmp_whitebalance.manual_blue = tmp_whitebalance.read_red = tmp_whitebalance.read_blue = PWC_WB_AUTO;
417   
418   if (ioctl(fd, VIDIOCPWCGAWB, &tmp_whitebalance)) 
419   {
420           snprintf(msg, ERRMSG_SIZ, "getWhiteBalance %s", strerror(errno));
421           cerr << msg << endl;
422   }
423   else
424   {
425#if 0
426      cout << "mode="<<tmp_whitebalance.mode
427           <<" mr="<<tmp_whitebalance.manual_red
428           <<" mb="<<tmp_whitebalance.manual_blue
429           <<" ar="<<tmp_whitebalance.read_red
430           <<" ab="<<tmp_whitebalance.read_blue
431           <<endl;
432#endif
433      /* manual_red and manual_blue are garbage :-( */
434      whiteBalanceMode_=tmp_whitebalance.mode;
435   }
436           
437      return whiteBalanceMode_;
438     
439      /*switch(whiteBalanceMode_) {
440      case PWC_WB_INDOOR:
441         setProperty("WhiteBalanceMode","Indor");
442         break;
443      case PWC_WB_OUTDOOR:
444         setProperty("WhiteBalanceMode","Outdoor");
445         break;
446      case PWC_WB_FL:
447         setProperty("WhiteBalanceMode","Neon");
448         break;
449      case PWC_WB_MANUAL:
450          setProperty("WhiteBalanceMode","Manual");
451          whiteBalanceRed_=tmp_whitebalance.manual_red;
452          whiteBalanceBlue_=tmp_whitebalance.manual_blue;
453
454         break;
455      case PWC_WB_AUTO:
456         setProperty("WhiteBalanceMode","Auto");
457         whiteBalanceRed_=tmp_whitebalance.read_red;
458         whiteBalanceBlue_=tmp_whitebalance.read_blue;
459         break;
460      default:
461         setProperty("WhiteBalanceMode","???");
462      }
463         
464      emit whiteBalanceModeChange(whiteBalanceMode_);
465
466      if (((whiteBalanceMode_ == PWC_WB_AUTO) && liveWhiteBalance_)
467          || whiteBalanceMode_ != PWC_WB_AUTO) {
468         setProperty("WhiteBalanceRed",whiteBalanceRed_);
469         emit whiteBalanceRedChange(whiteBalanceRed_);
470         setProperty("WhiteBalanceBlue",whiteBalanceBlue_);   
471         emit whiteBalanceBlueChange(whiteBalanceBlue_);
472         if (guiBuild()) {         
473            remoteCTRLWBred_->show();
474            remoteCTRLWBblue_->show();
475         }
476      } else {
477         if (guiBuild()) {         
478            remoteCTRLWBred_->hide();
479            remoteCTRLWBblue_->hide();
480         }
481      }
482   }*/
483}
484
485int V4L1_PWC::setWhiteBalance(char *errmsg) 
486{
487   struct pwc_whitebalance wb;
488   wb.mode=whiteBalanceMode_;
489   if (wb.mode == PWC_WB_MANUAL)
490   {
491      wb.manual_red=whiteBalanceRed_;
492      wb.manual_blue=whiteBalanceBlue_;
493   }
494   
495   if (ioctl(fd, VIDIOCPWCSAWB, &wb))
496   {
497       snprintf(errmsg, ERRMSG_SIZ, "setWhiteBalance %s", strerror(errno)); 
498       return -1;
499   }
500   
501   return 0;
502}
503
504int V4L1_PWC::setWhiteBalanceMode(int val, char *errmsg)
505 {
506   if (val == whiteBalanceMode_) 
507      return whiteBalanceMode_;
508     
509   if (val != PWC_WB_AUTO)
510   {
511      if ( val != PWC_WB_MANUAL)
512      {
513         whiteBalanceMode_=val;
514         if (setWhiteBalance(errmsg) < 0)
515           return -1;
516      }
517     
518      //whiteBalanceMode_=PWC_WB_AUTO;
519      whiteBalanceMode_= val;
520      if (setWhiteBalance(errmsg) < 0)
521       return -1;
522      getWhiteBalance();
523   }
524
525   /*if (guiBuild()) {
526      if (val != PWC_WB_AUTO
527          || ( liveWhiteBalance_ && (val ==PWC_WB_AUTO))) {
528         remoteCTRLWBred_->show();
529         remoteCTRLWBblue_->show();
530      } else {
531         remoteCTRLWBred_->hide();
532         remoteCTRLWBblue_->hide();
533      }
534   }*/
535   
536   whiteBalanceMode_=val;
537   if (setWhiteBalance(errmsg) < 0)
538    return -1;
539   getWhiteBalance();
540   
541   return 0;
542}
543
544int V4L1_PWC::setWhiteBalanceRed(int val, char *errmsg) 
545{
546   whiteBalanceMode_ = PWC_WB_MANUAL;
547   whiteBalanceRed_=val;
548   if (setWhiteBalance(errmsg) < 0)
549    return -1;
550   
551   return 0;
552}
553
554int V4L1_PWC::setWhiteBalanceBlue(int val, char *errmsg)
555{
556   whiteBalanceMode_ = PWC_WB_MANUAL;
557   whiteBalanceBlue_=val;
558   if (setWhiteBalance(errmsg) < 0)
559     return -1;
560     
561   return 0;
562}
563
Note: See TracBrowser for help on using the repository browser.