Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
VideoSource_V4L.cpp
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5 Multimediale Systeme der Informationsverarbeitung
6 Institut fuer Informatik
7 Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 
25 #include <sys/types.h>
26 #include <fcntl.h>
27 #include <stdio.h>
28 #include <unistd.h>
29 #include <sys/ioctl.h>
30 #include <sys/mman.h>
31 //#include <linux/videodev.h>
32 //#include <libv4lconvert.h>
33 #include <errno.h>
34 
35 
36 
37 #include "VideoSource_V4L.hh"
38 #include "VideoSourceCapabilities.hh"
39 #include <Base/Common/FileHandling.hh>
40 #include <Base/Debug/Exception.hh>
41 #include <Image/Camera.hh>
42 #include <Base/Image/ImageIO.hh>
43 
44 #define CLEAR(x) memset(&(x), 0, sizeof(x));
45 
46 using namespace BIAS;
47 using namespace std;
48 
49 
50 
53  : VideoSource()
54 {
55 
57  DefaultDevice_ = "/dev/video0";
58  ActiveFrame_ = 0;
59  SetDebugLevel(0);
60  // try PAL as default
61  Width_=768;
62  Height_=576;
64  DeviceChannel_=-1;
65  newFrame_=false;
66  if (pthread_mutex_init(&ActiveFrameMutex_, NULL)!=0)
67  BEXCEPTION("error initializing mutex");
68  // may be some time in the future.
69  // We could ask the V4L API if the device is controllable
70  IsControllable_ = false;
71  Frame_.resize(2);
72  ReadFirstFrame_ = false;
73  ControlBrightness_.id = 0;
74  ControlContrast_.id = 0;
75  ControlGain_.id = 0;
76  ControlAutoGain_.id = 0;
77  ControlShutter_.id = 0;
78  // SetDebugLevel(D_V4L);
79  fd = -1;
80  isJPEG_ = false;
81  BIASDOUT(D_V4L,"Contructor finished");
82  minBrightness_ =0; //additive offset in pixel values
83  maxBrightness_ = 100;
84 }
85 
86 
89 {
90  if (fd>=0) close(fd);
91  BIASDOUT(D_V4L,"Destructor finished");
92 
93 }
94 
95 
96 
98 GetAllDevices(std::vector<std::string> &devices)
99 {
100  BIASDOUT(D_V4L,"GetAllDevices()");
101  vector<string> devs;
102  string IdentifierBak = Identifier_;
103  ModelNameToDevice_.clear();
104  FileHandling::GetDirectoryContent("/dev","video","",devs,true);
105  for (unsigned int i=0;i<devs.size(); i++){
106  struct v4l2_capability cap;
107  string CoolName;
108  if ((fd = open(devs[i].c_str(), O_RDWR))>0) {
109  if (xioctl_(fd, (int)VIDIOC_QUERYCAP, &cap)>=0) {
110  Identifier_ = (char*)cap.card;
112  ModelNameToDevice_[Identifier_] = devs[i];
113  devices.push_back(Identifier_);
114 
115  }else
116  BIASERR("Enumerating devices, query capabilities failed for "<<devs[i]<<": "<<strerror(errno));
117  close(fd);
118  fd = -1;
119  } else
120  BIASERR("Enumerating devices, open() failed for "<<devs[i]<<": "<<strerror(errno));
121  } //for
122 
123  Identifier_ = IdentifierBak;
124  return devices.size();
125 }
126 
127 
128 
131 {
132  return GetCapabilities(DefaultDevice_,caps);
133 }
134 
135 
137 GetCapabilities(const char *device, VideoSourceCapabilities &caps)
138 {
139  deviceChannelNames_.clear();
140  BIASDOUT(D_V4L,string("GetCapabilities() for device ")+device);
141  caps.Reset();
142  string usedev;
143  if (device[0] != '/') {
144  usedev = ModelNameToDevice_[device];
145  if (usedev =="") return -2;
146  }
147  else usedev =device;
148  if ((fd = open(usedev.c_str(), O_RDWR))<0) {
149  fd = -1;
150  BEXCEPTION("Failed to open device: "<<usedev<<" "<<strerror(errno));
151  }
152 
153  if (xioctl_(fd,(int)VIDIOC_QUERYCAP,&capability2)<0) {
154  close(fd);
155  fd = -1;
156  BEXCEPTION("Failed to query capabilities: "<<strerror(errno));
157  }
158  caps.SetName(string((char*)capability2.card));
159 
160 #ifdef BIAS_DEBUG
161  cout << "driver: " << capability2.driver << "\n";
162  cout << "Bus: " << capability2.bus_info <<endl;
163  cout<< "Version: " << capability2.version <<endl;
164  if (capability2.capabilities & V4L2_CAP_VIDEO_CAPTURE)
165  cout<<"The device supports the video capture interface."<<endl;
166  if (capability2.capabilities & V4L2_CAP_VIDEO_OUTPUT)
167  cout<<"The device supports the video output interface."<<endl;
168  if (capability2.capabilities &V4L2_CAP_VIDEO_OVERLAY)
169  cout<<"The device supports the video overlay interface. Overlay "
170  "typically stores captured images directly in the video memory "
171  "of a graphics card, with support for clipping."<<endl;
172  if (capability2.capabilities & V4L2_CAP_VBI_CAPTURE)
173  cout<<"The device supports the VBI capture interface"<<endl;
174  if (capability2.capabilities & V4L2_CAP_TUNER)
175  cout<<"The device has a tuner of some form"<<endl;
176  if (capability2.capabilities & V4L2_CAP_AUDIO)
177  cout<<"The device has audio inputs or outputs."<<endl;
178  if (capability2.capabilities &V4L2_CAP_READWRITE)
179  cout<<"The device supports the read() and/or write() I/O methods."<<endl;
180  if (capability2.capabilities & V4L2_CAP_ASYNCIO)
181  cout<<"The device supports the asynchronous I/O methods."<<endl;
182  if (capability2.capabilities & V4L2_CAP_STREAMING)
183  cout<<"The device supports the streaming I/O method."<<endl;
184 #endif
185  // if CAPTURE device print info about all inputs
186  int index=0, current=-1;
187  struct v4l2_input input;
188  memset (&input, 0, sizeof (input));
189  input.index = index;
190  if (xioctl_(fd,(int)VIDIOC_G_INPUT, &current)!=0){
191  perror("couldn't get current active input number");
192  }
193 
194  while (xioctl_(fd, (int)VIDIOC_ENUMINPUT, &input)==0) {
196  InpDesc.number = index;
197  InpDesc.name = (char*)input.name;
198  if (input.type == V4L2_INPUT_TYPE_CAMERA)
200 
201  if (input.type == V4L2_INPUT_TYPE_TUNER)
203 
204  //cout<<"Supported standards:";
205  // if (input.std & V4L2_STD_PAL ) cout<<"PAL ";
206  // if (input.std & V4L2_STD_NTSC ) cout<<"NTSC ";
207  // if (input.std & V4L2_STD_SECAM ) cout<<"SECAM ";
208  //cout<<endl;
209  if (index==current) {
210  InpDesc.Active = true;
211  if (input.status & V4L2_IN_ST_NO_POWER) InpDesc.NoPower = true;
212  else InpDesc.NoPower = false;
213  if (input.status & V4L2_IN_ST_NO_SIGNAL) InpDesc.NoSignal = true;
214  else InpDesc.NoSignal = false;
215  if (input.status & V4L2_IN_ST_NO_COLOR) InpDesc.NoColor = true;
216  InpDesc.NoColor = false;
217  }
218  else InpDesc.Active = false;
219 
220  //back up channel names
221  deviceChannelNames_.push_back(InpDesc.name);
222 
223  caps.AddInput(InpDesc);
224  index++;
225  input.index = index;
226  usleep(1000); //wait 1ms
227  }
228  if (index==0) {
229  cerr<<"No Input found. Error:";
230  if (errno==EBUSY) cout<<"EBUSY"<<endl;
231  if (errno==EINVAL) cout<<"EINVAL"<<endl;
232  else cout<<errno<<endl;
233  }
234 
235 
236  struct v4l2_fmtdesc fmtdesc;
237  fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
238  fmtdesc.index = 0;
239 
240  while (xioctl_(fd,(int)VIDIOC_ENUM_FMT,&fmtdesc) ==0 ) {
242  switch(fmtdesc.pixelformat) {
243  case v4l2_fourcc('B', 'G', 'R', '3'): cm = ImageBase::CM_BGR; break;
244  case v4l2_fourcc('R', 'G', 'B', '3'): cm = ImageBase::CM_RGB; break;
245  case v4l2_fourcc('Y', 'U', 'Y', 'V'): cm = ImageBase::CM_YUYV422; break;
246  case v4l2_fourcc('U', 'Y', 'V', 'Y'): cm = ImageBase::CM_UYVY422; break;
247  case v4l2_fourcc('G', 'B', 'R', 'G'): cm = ImageBase::CM_Bayer_GBRG; break;
248  case v4l2_fourcc('B', 'A', '8', '1'): cm = ImageBase::CM_Bayer_BGGR; break;
249  case v4l2_fourcc('G', 'R', 'E', 'Y'): cm = ImageBase::CM_Grey; break;
250  //todo add switches for other color models:
251  //HI24 RGBO RGBQ RGBP RGBR BGR4 RGB4 422P YU12 YV12 411P YUV9 YVU9
252  default: {
253  char tmp[10];
254  memcpy(tmp, (char*)&fmtdesc.pixelformat,4);
255  tmp[4]=0;
256  //cout <<"unsupported pixelformat: "<<tmp<<endl;
258  }
259  }//end switch
260 
261  if (cm != ImageBase::CM_invalid) {
262  //cout<<"FOUND VALID ColorMode:"<<fmtdesc.pixelformat<<endl;
263  struct v4l2_frmsizeenum frmsizeenum;
264  frmsizeenum.index = 0;
265  frmsizeenum.pixel_format = fmtdesc.pixelformat;
266  bool interlace = true;
267  switch(fmtdesc.pixelformat)
268  {
269  case V4L2_FIELD_NONE:
270  interlaceMode_ = V4L2_FIELD_NONE;
271  interlace=false;
272  break;
273  case V4L2_FIELD_ANY:
274  case V4L2_FIELD_TOP :
275  case V4L2_FIELD_BOTTOM :
276  case V4L2_FIELD_INTERLACED:
277  case V4L2_FIELD_SEQ_TB:
278  case V4L2_FIELD_SEQ_BT:
279  case V4L2_FIELD_ALTERNATE:
280  case V4L2_FIELD_INTERLACED_TB :
281  case V4L2_FIELD_INTERLACED_BT:
282  interlaceMode_ = V4L2_FIELD_INTERLACED;
283  interlace = true;
284  break;
285  default:
286  interlace = false;
287  interlaceMode_ = V4L2_FIELD_NONE;
288  //cout<<"Unknown interlace type:"<<fmtdesc.pixelformat<<endl;
289  break;
290  }
291 
292  while (-1 != xioctl_(fd,(int)VIDIOC_ENUM_FRAMESIZES,&frmsizeenum)) {
293  cout <<" Framesize type: "<<frmsizeenum.type<<endl;
294  switch (frmsizeenum.type)
295  {
296  case V4L2_FRMSIZE_TYPE_DISCRETE: {
297  struct v4l2_frmivalenum frmivalenum;
298  frmivalenum.pixel_format = fmtdesc.pixelformat;
299  frmivalenum.width = frmsizeenum.discrete.width;
300  frmivalenum.height = frmsizeenum.discrete.height;
301  frmivalenum.index = 0;
302 
303  float fps;
304  while (xioctl_(fd,(int)VIDIOC_ENUM_FRAMEINTERVALS, &frmivalenum) ==0) {
305  switch (frmivalenum.type) {
306  case V4L2_FRMIVAL_TYPE_DISCRETE:
307  fps = (float)frmivalenum.discrete.denominator/(float)frmivalenum.discrete.numerator;
308  caps.AddMode(frmsizeenum.discrete.width,frmsizeenum.discrete.height,fps,cm,interlace);
309  cout<<"Adding Mode:"<<frmsizeenum.discrete.width<<","<<frmsizeenum.discrete.height<<endl;
310  break;
311  case V4L2_FRMIVAL_TYPE_STEPWISE:
312  break;
313  case V4L2_FRMIVAL_TYPE_CONTINUOUS:
314  break;
315  }
316  frmivalenum.index ++;
317  }
318  }
319  break;
320  case V4L2_FRMSIZE_TYPE_CONTINUOUS:
321  BIASERR("VideoSourceCapabilities can not handle continuous frame sizes");
322  break;
323  case V4L2_FRMSIZE_TYPE_STEPWISE:
324  BIASERR("VideoSourceCapabilities can not handle continuous frame sizes");
325  break;
326  }
327  cout<<"we found :"<<frmsizeenum.index<<" valid configurations."<<endl;
328  frmsizeenum.index++;
329 
330  } // while () for all frmsizees
331  } // if (cm != ImageBase::CM_invalid)
332  else{
333  ;//cout<<"Invalid ColorMode:"<<fmtdesc.pixelformat<<endl;
334  }
335  fmtdesc.index++;
336  } // while () for all pixelformats
337  close(fd);
338  fd = -1;
339  return 0;
340 }
341 
343 GetDeviceChannelNames(std::vector<std::string> &names){
344  names = deviceChannelNames_;
345 }
346 
349 {
350  return OpenDevice(DefaultDevice_);
351 }
352 
353 
355 OpenDevice(const char *device)
356 {
357  string usedev;
358  if (device[0] != '/') {
359  if (ModelNameToDevice_.empty()) {
360  vector<string> tmp;
361  GetAllDevices(tmp);
362  device = tmp[0].c_str();
363  }
364  cout<<"Device in OpenDevice:"<<device<<endl;
365  usedev = ModelNameToDevice_[device];
366  if (usedev =="") BEXCEPTION("Unknown device "<<device);
367  BIASDOUT(D_V4L,string("OpenDevice(")+device+") will use "+usedev);
368  }
369  else {
370  usedev =device;
371  BIASDOUT(D_V4L,string("OpenDevice() will use ")+usedev);
372  }
373 #ifdef BIAS_DEBUG
374  cout<<"Opening device :"<<usedev<<endl;
375 #endif
376  if ((fd = open(usedev.c_str(), O_RDWR))<0){
377  BIASERR("Failed to open device: "<<usedev<<" "<<strerror(errno));
378  return -1;
379  }
380 
381  if (xioctl_(fd,(int)VIDIOC_QUERYCAP,&capability2)<0){
382  BIASERR("Failed query capabilities: "<<strerror(errno));
383  return -1;
384  }
385 
386  // at first try to select the input/channel where a signal is
387  // only if none ist set by the user
388 
389  int index =0;
390 #ifdef BIAS_DEBUG
391  cout<<"V4L device channel:"<<DeviceChannel_<<endl;
392 #endif
393  if (DeviceChannel_>=0) {
394  index = DeviceChannel_;
395  }
396 
397  struct v4l2_input input;
398  int res=0;
399  res=ioctl(fd, VIDIOC_S_INPUT, &index);
400  if (res!=0){
401  perror("VIDIOC_S_INPUT: couldn't set active input:");
402  }
403  bool found =false;
404  while (!found && res==0) {
405  // check wether there is a signal and color
406  memset (&input, 0, sizeof (input));
407  input.index = index;
408  usleep(50);
409  if (ioctl(fd, VIDIOC_ENUMINPUT, &input)==0) {
410  if (input.status==0) {
411  found=true; // input with a valid signal found
412  // cout<<"valid signal on input channel:"<<index<<" found."<<endl;
413  }
414  }
415  if (!found) {
416  usleep(50);
417  index++;
418  res=xioctl_(fd, (int)VIDIOC_S_INPUT, &index);
419  if (res!=0)
420  cerr<<"VIDIOC_S_INPUT: couldn't set active input:"<<index<<endl;
421  }
422  }
423  if (!found) {
424  close(fd);
425  fd = -1;
426  BIASERR("No valid input signal found on all "<<index+1<<" channels");
427  return -1;
428  }
429 
430  res = InitDevice_();
431  if (res!=0) return res;
432 
433  res = InitMMap_();
434  if (res!=0) return res;
435 
436  CompleteInitialized_ = true;
437 
438 #ifdef BIAS_HAVE_LIBJPEG
439  if (isJPEG_) {
440  if (Decompressor_.Init() < 0) {
441  BIASERR("Could not initialize JPEG-compression!!!");
442  return -1;
443  }
444  else cout<<"Initialized jpeg decompressor."<<endl;
445  }
446 #else //BIAS_HAVE_LIBJPEG
447  if (isJPEG_) {
448  BIASERR("Compression mode not available without LIBJPEG!");
449  }
450 #endif //BIAS_HAVE_LIBJPEG
451 
452  InitImage(Frame_[0]);
453  InitImage(Frame_[1]);
454 
455  //ImageIO::Save("Frame.mip", Frame_[0]);
456 
457  return 0;
458 }
459 
461 OpenDevice(int device)
462 {
463  char dev[256];
464  sprintf(dev, "/dev/video%d", device);
465  return OpenDevice(dev);
466 }
467 
470 {
471  BIASDOUT(D_V4L,"Closing device");
472  if (Active_) PostGrab();
473 
474  Grabbing_ = false;
475 
476  CompleteInitialized_ = false;
477 
478  int res = 0;
479  res = UninitMMap_();
480  if (res!=0) {
481  BIASERR("UninitMMap_() Failed ");
482  return res;
483  }
484 
485  if (-1 == close(fd)){
486  cerr << "error calling close()\n";
487  perror("close");
488  }
489  fd = -1;
490  return 0;
491 
492 }
493 
494 
495 
498 {
499  // BIASDOUT(D_V4L,"VideoSource_V4L::GrabSingle()");
500  assert(!image.IsEmpty());
501  if (!Active_) BEXCEPTION("VideoSource Object not active, use PreGrab()");
502  if (Grabbing_) BEXCEPTION("VideoSource Object is already grabbing()");
503 
504  Grabbing_ = true;
505  //check Active multiple times to be really sure
506  if (Active_ ) { // Has PreGrab() spawned a grab thread?
507  // Has that thread delivered an image ? If not, wait;
508  while (!ReadFirstFrame_) usleep(1000);
509  }
510 
511  if (Active_ ) {
512  if (WaitForNew_) while (!newFrame_) usleep(500);
513  }
514 
515  pthread_mutex_lock(&ActiveFrameMutex_);
516  if (Active_ ) {
517  // locking not necessary because more than 2 buffers are used fro grabbing
518  gettimeofday(&GrabTime_,NULL);
519  image.SetTime(GrabTime_.tv_sec,GrabTime_.tv_usec);
520  newFrame_ = false;
521  //cout << "GrabSingle, returning Frame_["<<(int)(ActiveFrame_)<<"] ... "<<flush;
522 
523 #ifdef BIAS_DEBUG
524  if (Frame_[ActiveFrame_].GetSizeByte() != image.GetSizeByte()) {
525  BIASERR("intern buffer has size: "<<Frame_[ActiveFrame_].GetSizeByte()
526  <<"target buffer has size: "<<image.GetSizeByte());
527  }
528 #endif
529  if(Frame_[ActiveFrame_].GetImageData()==NULL){
531  Frame_[ActiveFrame_].GetHeight(),Frame_[ActiveFrame_].GetChannelCount());
532  }
533  image.CopyIn_NoInit((unsigned char*)Frame_[ActiveFrame_].GetImageData());
534  //cout << " done\n";
535  } else { // no grab thread has to do the hard work
536  buffer_.index=0; // always use first buffer, if not in continous mode
537  if (xioctl_(fd, (int)VIDIOC_QBUF, &buffer_)!=0) {
538  perror("ioctl: freeing the buffer memory\n");
539  Grabbing_ = false;
540  pthread_mutex_unlock(&ActiveFrameMutex_);
541  return -3;
542  }
543  errno=0;
544  // wait for a new frame
545  while ( (errno!=EINVAL) &&
546  (xioctl_(fd, (int)VIDIOC_DQBUF, &buffer_)!=0) ) {
547  if (errno==EINVAL) {
548  Grabbing_ = false;
549  //BEXCEPTION("Error while waiting for a new frame: "<<strerror(errno));
550  BIASERR("Error while waiting for a new frame: "<<strerror(errno));
551  pthread_mutex_unlock(&ActiveFrameMutex_);
552  return -4;
553  }
554  }
555  gettimeofday(&GrabTime_,NULL);
556  image.SetTime(GrabTime_.tv_sec,GrabTime_.tv_usec);
557  image.CopyIn_NoInit( (unsigned char*)Buffers_[0].start);
558  }
559  pthread_mutex_unlock(&ActiveFrameMutex_);
560 
561  Grabbing_ = false;
562 
563  image.InvalidateUID();
564  image.SetUID(UUID::GenerateUUID());
565 
566  // BIASDOUT(D_V4L,"leaving GrabSingle()");
567 
568  return 0;
569 }
570 
573 {
574  BIASDOUT(D_V4L,"PreGrab()");
575  Active_ = true;
576  int res = StartCapturing_();
577  if (res!=0){// BEXCEPTION("StartCapturing_() failed");
578  BIASERR("StartCapturing_() failed");
579  return -1;
580  }
581  pthread_attr_t attributes;
582  pthread_attr_init(&attributes);
583  int detachstate;
584  pthread_attr_getdetachstate(&attributes,&detachstate);
585  // cout <<"Thread detach state: "<<detachstate<<endl<<" joinable would be: "
586  // <<PTHREAD_CREATE_JOINABLE<<endl;
587  pthread_attr_setdetachstate(&attributes,PTHREAD_CREATE_JOINABLE);
588  //pthread_mutex_init(&ActiveFrameMutex_, NULL) ||
589  return pthread_create(&ContinousThread_, &attributes, GrabContThread_ , this);
590 }
591 
592 
595 {
596  BIASDOUT(D_V4L,"PostGrab()");
597  int res = 0;
598  if (Active_) {
599  Active_ = false;
600  usleep(1000);
601  if ( (res = pthread_join(ContinousThread_, NULL)) != 0){
602  BIASERR("VideoSource_V4L::PostGrab() pthread_join unsucessfull: "
603  << strerror(errno));
604  }
605  }
606  pthread_mutex_unlock(&ActiveFrameMutex_);
607  res = StopCapturing_();
608  if (res!=0) BIASERR("StopCapturing_() failed");
609  return 0;
610 }
611 
612 
613 
616 {
617  if (Identifier_.find("UVC Camera") != string::npos) {
618  cout <<"This is an UVC-Camera on USB, Identifier: "<<Identifier_<<endl;
619  int StartOfId = Identifier_.find('(')+1;
620  string USBID = Identifier_.substr(StartOfId,9);
621  /// try to extract vendor/product string from
622  /// system's map file
623  /// mapfile's syntax:
624  /// vendorID vendor string
625  /// \t productID product
626  string mapfile;
627  vector<string> possibleMapFiles;
628  /// to be extended as necessary
629  possibleMapFiles.push_back("/var/lib/misc/usb.ids"); /// ubuntu jaunty
630  for ( unsigned f=0; f<possibleMapFiles.size(); f++ ) {
631  ifstream ifs(possibleMapFiles[f].c_str());
632  if (ifs) {
633  mapfile = possibleMapFiles[f];
634  ifs.close();
635  break;
636  }
637  }
638  if ( mapfile == "" ) return;
639 
640  string vendorID = USBID.substr(0,4);
641  string productID = USBID.substr(5,4);
642  string identifier;
643 
644  ifstream ifs(mapfile.c_str());
645  if (!ifs) cerr << "Cannot open file: " << mapfile << endl;
646  else {
647 
648  /// first: find vendor
649  while ( !ifs.eof() ) {
650  string tmp;
651  getline(ifs, tmp);
652  if ( tmp.substr(0,4) == vendorID ) {
653  int vendorStart = tmp.find_first_not_of(" ", 4);
654  identifier = tmp.substr(vendorStart);
655  //cout << "found vendor " << identifier << endl;
656  /// found vendor, stop
657  break;
658  }
659  } // end while vendor
660 
661  /// second: find product
662  while ( !ifs.eof() ) {
663  string tmp;
664  getline(ifs, tmp);
665  int productIDStart = tmp.find_first_not_of("\t ");
666  if ( productIDStart == 0 ) {
667  /// reached next vendor, i.e. no product found
668  break;
669  }
670  if ( tmp.substr(productIDStart, 4) == productID ) {
671  tmp = tmp.substr(productIDStart);
672  int productIDEnd = tmp.find_first_of(" ");
673  int productStart = tmp.find_first_not_of(" ", productIDEnd);
674  if ( identifier != "" ) identifier += " ";
675  identifier += tmp.substr(productStart);
676  //cout << " found product " << tmp.substr(productStart) << endl;
677  /// found product, stop
678  break;
679  }
680  } // end while product
681 
682  ifs.close();
683 
684  }
685 
686  if ( identifier != "" ) {
687  Identifier_ = identifier;
688  cout <<" New Identifiers_ "<<Identifier_<<endl;
689  }
690  } // if("UVC camera")
691  else {
692  // fkellner 15.2.11 why is this converted to utf8?
693  // Identifier_ = IsoLatin1ToUtf8(Identifier_);
694  }
695 }
696 
697 
698 void *VideoSource_V4L::
699 GrabContThread_(void * arg)
700 {
701  VideoSource_V4L *obj = (VideoSource_V4L *)arg;
702 
703  while (obj->Active_){
704 
705  fd_set fds;
706  struct timeval tv;
707  int r;
708 
709  FD_ZERO (&fds);
710  FD_SET (obj->fd, &fds);
711 
712  /* Timeout. */
713  tv.tv_sec = 2;
714  tv.tv_usec = 0;
715 
716  r = select(obj->fd + 1, &fds, NULL, NULL, &tv);
717 
718  if (-1 == r) {
719  if (EINTR == errno){
720  continue;
721  }
722  cerr << "select\n";
723  perror("select");
724  return NULL;
725  }
726 
727  if (0 == r) {
728  cerr << "select timeout\n";
729  continue;
730  //return NULL;
731  }
732 
733  if ( obj->ReadFrame_() != 0 ) {
734  cerr << "lost camera\n";
735  obj->Active_ = false;
736  }
737 
738  /* EAGAIN - continue select loop. */
739  }
740 #ifdef BIAS_DEBUG
741  cout <<"finished grab thread"<<endl;
742 #endif
743  pthread_exit(NULL);
744 }
745 
746 
747 int VideoSource_V4L::
748 InitMMap_()
749 {
750  // cout << "InitMMap_()\n";
751  struct v4l2_requestbuffers req;
752  CLEAR(req);
753 
754  req.count = 4;
755  req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
756  req.memory = V4L2_MEMORY_MMAP;
757 
758  if (-1 == xioctl_(fd, (int)VIDIOC_REQBUFS, &req)) {
759  if (EINVAL == errno)
760  BEXCEPTION("Device does not support memory mapping:"<<strerror(errno))
761  else
762  BEXCEPTION("Failed to request buffers: "<<strerror(errno));
763  }
764 
765  if (req.count < 2)
766  BEXCEPTION("Insufficient buffer memory, need at least 2 buffers"<<strerror(errno));
767 
768  Buffers_.resize(req.count);
769 
770  for (unsigned i = 0; i < req.count; ++i) {
771  struct v4l2_buffer buf;
772 
773  CLEAR (buf);
774 
775  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
776  buf.memory = V4L2_MEMORY_MMAP;
777  buf.index = i;
778 
779  if (-1 == xioctl_(fd, (int)VIDIOC_QUERYBUF, &buf))
780  BEXCEPTION("Failed to query buffer: "<<strerror(errno));
781 
782  Buffers_[i].length = buf.length;
783  Buffers_[i].start =
784  mmap (NULL /* start anywhere */,
785  buf.length,
786  PROT_READ | PROT_WRITE /* required */,
787  MAP_SHARED /* recommended */,
788  fd, buf.m.offset);
789 
790  if (MAP_FAILED == Buffers_[i].start)
791  BEXCEPTION("Failed to map memory: "<<strerror(errno));
792  }
793  return 0;
794 }
795 
796 
797 int VideoSource_V4L::
798 xioctl_(int fd, int request, void *arg)
799 {
800  int r;
801  do r = ioctl(fd, request, arg);
802  while (-1 == r && EINTR == errno);
803 
804  return r;
805 }
806 
807 
808 int VideoSource_V4L::
809 StartCapturing_()
810 {
811  enum v4l2_buf_type type;
812 
813  const unsigned num_buf = Buffers_.size();
814  for (unsigned i = 0; i < num_buf; ++i) {
815  struct v4l2_buffer buf;
816 
817  CLEAR (buf);
818 
819  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
820  buf.memory = V4L2_MEMORY_MMAP;
821  buf.index = i;
822 
823  if (-1 == xioctl_(fd, (int)VIDIOC_QBUF, &buf)){
824  BIASERR("error: ioctl VIDIOC_QBUF:"<<strerror(errno));
825  return -1;
826  }
827  }
828 
829  type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
830 
831  if (-1 == xioctl_(fd, VIDIOC_STREAMON, &type)){
832  //BEXCEPTION("Failed to activate streaming from device :"<<strerror(errno))
833  BIASERR("Failed to activate streaming from device :"<<strerror(errno));
834  return -2;
835  }
836  return 0;
837 }
838 
839 int VideoSource_V4L::
840 StopCapturing_()
841 {
842  enum v4l2_buf_type type;
843  type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
844 
845  if (-1 == xioctl_(fd, VIDIOC_STREAMOFF, &type))
846  BEXCEPTION("Failed to deactivate streaming from device :"<<strerror(errno))
847 
848 
849  return 0;
850 }
851 
852 
853 int VideoSource_V4L::
854 UninitMMap_()
855 {
856  // cout << "UninitMMap_()\n";
857  const unsigned num_bufs = Buffers_.size();
858  for (unsigned i = 0; i < num_bufs; ++i){
859  if (-1 == munmap (Buffers_[i].start, Buffers_[i].length))
860  BEXCEPTION("Failed unmap memory :"<<strerror(errno))
861  }
862  return 0;
863 }
864 
865 
866 int VideoSource_V4L::
867 ReadFrame_()
868 {
869  struct v4l2_buffer buf;
870 
871  CLEAR(buf);
872 
873  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
874  buf.memory = V4L2_MEMORY_MMAP;
875 
876  if (-1 == xioctl_(fd, (int)VIDIOC_DQBUF, &buf)) {
877  switch (errno) {
878  case EAGAIN:
879  cerr << "cannot DQBUF\n";
880  return -1;
881  case EIO:
882  /* Could ignore EIO, see spec. */
883  /* fall through */
884  default:
885  perror("ioctl: VIDIOC_DQBUF");
886  return -1;
887  }
888  }
889  assert(buf.index < Buffers_.size());
890 
891  pthread_mutex_lock(&ActiveFrameMutex_);
892  //cout << "filling Frame_["<<(int)(!ActiveFrame_)<<"] ... ";
893  assert(ActiveFrame_==0 || ActiveFrame_==1);
894  assert((!ActiveFrame_)==0 || (!ActiveFrame_)==1);
895  assert(Frame_.size()==2);
896  unsigned num = Frame_[!ActiveFrame_].GetPixelCount()*
897  Frame_[!ActiveFrame_].GetChannelCount()*Frame_[!ActiveFrame_].GetDepth();
898 
899  if (num != Buffers_[buf.index].length){
900  Frame_[!ActiveFrame_].PrintHeader();
901 
902  if (isJPEG_) {
903 #ifdef BIAS_HAVE_LIBJPEG
904  Decompressor_.SetCompressedData((void *)&(Buffers_[buf.index]),
905  (long) Buffers_[buf.index].length);
906  /*
907  struct v4lconvert_data data;
908  int res = v4lconvert_needs_conversion(&data,format2_,formatRGB_);
909  if(res != 0){
910  jpeg_.Release(false);
911  jpeg_.Init(GetWidth(),GetHeight(),GetColorChannels());
912  unsigned lengthJPEG;
913  lengthJPEG = jpeg_.GetPixelCount()*jpeg_.GetChannelCount()*jpeg_.GetDepth();
914  unsigned char * idJPEG = jpeg_.GetImageData();
915  res = v4lconvert_convert(&data,format2_,formatRGB_,
916  &(Buffers_[buf.index]),Buffers_[buf.index].length,idJPEG,lengthJPEG);
917  }
918  */
919  if (Decompressor_.Decompress(jpegImg_,true) < 0) {
920  BIASERR("Decompression failed!");
921  return -1;
922  }
923  if (Frame_[!ActiveFrame_].SamePixelAndChannelCount(jpegImg_))
924  Frame_[!ActiveFrame_].CopyIn_NoInit(jpegImg_.GetImageData());
925  else
927 #endif
928  }
929  else{
930  cerr << "buffer and image size mismatch: "<<num<<"\t"
931  <<Buffers_[buf.index].length<<endl;
932  BIASASSERT(num <= Buffers_[buf.index].length);
933  }
934  }
935  else{
937  CopyIn_NoInit((unsigned char*)Buffers_[buf.index].start);
938  }
939 
941  newFrame_ = true;
942  if (!ReadFirstFrame_) ReadFirstFrame_=true;
943  //cout << "done\n";
944  pthread_mutex_unlock(&ActiveFrameMutex_);
945 
946  if (-1 == xioctl_(fd, (int)VIDIOC_QBUF, &buf)){
947  cerr << "ioctl: VIDIOC_QBUF\n";
948  perror("ioctl: VIDIOC_QBUF");
949  return -1;
950  }
951 
952  return 0;
953 }
954 
955 
956 int VideoSource_V4L::
957 InitDevice_()
958 {
959  struct v4l2_capability cap;
960  struct v4l2_cropcap cropcap;
961  struct v4l2_crop crop;
962  struct v4l2_format fmt;
963  unsigned int min;
964 
965  if (-1 == xioctl_(fd, (int)VIDIOC_QUERYCAP, &cap)) {
966  if (EINVAL == errno) {
967  perror("not a V4L2 device");
968  return -1;
969  } else {
970  perror("InitDevice_() ioctl: VIDIOC_QUERYCAP");
971  return -2;
972  }
973  }
974  Identifier_ = (char*)cap.card;
976 
977  if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
978  BEXCEPTION("No video capture device");
979 
980  if (!(cap.capabilities & V4L2_CAP_STREAMING))
981  BEXCEPTION("This device does not support streaming i/o");
982 
983  /* Select video input, video standard and tune here. */
984  CLEAR (cropcap);
985 
986  cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
987 
988  if (0 == xioctl_(fd, (int)VIDIOC_CROPCAP, &cropcap)) {
989  crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
990  crop.c = cropcap.defrect; /* reset to default */
991 
992  if (-1 == xioctl_(fd, VIDIOC_S_CROP, &crop)) {
993  switch (errno) {
994  case EINVAL:
995  /* Cropping not supported. */
996  break;
997  default:
998  /* Errors ignored. */
999  break;
1000  }
1001  }
1002  } else {
1003  /* Errors ignored. */
1004  }
1005 
1006 
1007  CLEAR (fmt);
1008 
1009  fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1010  fmt.fmt.pix.width = Width_;
1011  fmt.fmt.pix.height = Height_;
1012  // cout<<"Opening with colormode:"<<ColorMode_<<" and:"<<Width_<<"x"<<Height_<<" pixel"<<endl;
1013 
1014  switch (ColorMode_) {
1015  case ImageBase::CM_Grey:
1016  fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_GREY;
1017  break;
1018  case ImageBase::CM_YUYV422:
1019  fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
1020  break;
1021  case ImageBase::CM_RGB:
1022  fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
1023  break;
1024  case ImageBase::CM_BGR:
1025  fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24;
1026  break;
1027  case ImageBase::CM_BGRA:
1028  fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR32;
1029  break;
1031  fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SGBRG8;
1032  break;
1034  fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
1035  break;
1036  default:
1037  BEXCEPTION("Unsupported color model: "<<ColorMode_);
1038  break;
1039  }
1040  //why are we always using interlaced images??
1041  //todo add check for interlaced images and set here correctly
1042  fmt.fmt.pix.field = interlaceMode_;
1043 
1044  // check if the requested format exists
1045  if (-1 == xioctl_(fd, (int)VIDIOC_TRY_FMT, &fmt)){
1046  BIASERR("Unable to set video device to requested format, "
1047  "falling back to 640x480 YUYV");
1048  CLEAR (fmt);
1049  fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1050  fmt.fmt.pix.width = 640;
1051  fmt.fmt.pix.height = 480;
1052  fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
1053  fmt.fmt.pix.field = V4L2_FIELD_ANY;
1054  }
1055 
1056  if (-1 == xioctl_(fd, (int)VIDIOC_S_FMT, &fmt))
1057  BEXCEPTION("Failed to set video format: "<<strerror(errno));
1058 
1059 
1060  /* Note VIDIOC_S_FMT may change width and height. */
1061 
1062  /* Buggy driver paranoia. */
1063  min = fmt.fmt.pix.width * 2;
1064  if (fmt.fmt.pix.bytesperline < min)
1065  fmt.fmt.pix.bytesperline = min;
1066  min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
1067  if (fmt.fmt.pix.sizeimage < min)
1068  fmt.fmt.pix.sizeimage = min;
1069 
1070  Width_ = fmt.fmt.pix.width;
1071  Height_ = fmt.fmt.pix.height;
1072  BytesPerPixel_ = 1.; // only unsigned char images
1073  //cout<<fmt.fmt.pix.pixelformat<<" RGB:"<< V4L2_PIX_FMT_RGB24 <<endl;
1074  switch (fmt.fmt.pix.pixelformat){
1075  case V4L2_PIX_FMT_GREY:
1077  ColorChannels_ = 1;
1078  break;
1079  case V4L2_PIX_FMT_YUYV:
1081  ColorChannels_ = 2;
1082  break;
1083  case V4L2_PIX_FMT_RGB24:
1085  ColorChannels_ = 3;
1086  break;
1087  case V4L2_PIX_FMT_BGR24:
1089  ColorChannels_ = 3;
1090  break;
1091  case V4L2_PIX_FMT_BGR32:
1092  cout<<"Set color mode to BGRA"<<endl;
1094  ColorChannels_ = 4;
1095  break;
1096  case V4L2_PIX_FMT_SGBRG8:
1097  cout<<"Thats it Bayer GBRG"<<endl;
1099  ColorChannels_ = 2;
1100  break;
1101  case V4L2_PIX_FMT_JPEG:
1102  cout<<"Thats it JPEG/JFIF"<<endl;
1104  ColorChannels_ = 1;
1105  struct v4l2_jpegcompression compression;
1106  if (xioctl_(fd, (int)VIDIOC_G_JPEGCOMP, &compression)==0) {
1107  cout<<"Got jpeg compression params"<<endl;
1108  cout<<"compression.quality:"<<compression.quality<<endl;
1109  cout<<"compression.APPn:"<<compression.APPn<<endl;
1110  cout<<"compression.APP_len:"<<compression.APP_len<<endl;
1111  cout<<"compression.COM_len:"<<compression.COM_len<<endl;
1112  isJPEG_ = true;
1113  }
1114  else BIASERR("Could not get jpeg compression parameters.");
1115 
1116  break;
1117  default:
1118  BIASERR("unknown color model:"<<fmt.fmt.pix.pixelformat);
1119  return -5;
1120  break;
1121  }
1122 
1123  struct v4l2_queryctrl controls;
1124  // for (controls.id=V4L2_CID_BASE; controls.id<V4L2_CID_LASTP1;
1125  // controls.id++) {
1126  for (controls.id=V4L2_CID_BASE; controls.id<V4L2_CID_LASTP1-23;
1127  controls.id++) { // for the sony PTZ
1128  unsigned int tmpID = controls.id;
1129  if(controls.id == V4L2_CID_BASE+4) continue;
1130  if(controls.id == V4L2_CID_BASE+5) continue;
1131  // if(controls.id == V4L2_CID_BASE+10) continue;
1132  // ...
1133  // if(controls.id == V4L2_CID_BASE+32) continue;
1134  if (xioctl_(fd, (int)VIDIOC_QUERYCTRL, &controls)==0) {
1135 #ifdef BIAS_DEBUG
1136  cout <<"control valid: V4L2_CID_BASE+"<<controls.id-V4L2_CID_BASE
1137  <<" name: "<<controls.name<<endl;
1138 #endif
1139  switch (controls.id){
1140  case V4L2_CID_BRIGHTNESS:
1141  memcpy(&ControlBrightness_,&controls, sizeof(controls));
1142  break;
1143  case V4L2_CID_CONTRAST:
1144  memcpy(&ControlContrast_,&controls, sizeof(controls));
1145  break;
1146  case V4L2_CID_GAIN:
1147  memcpy(&ControlGain_,&controls, sizeof(controls));
1148  break;
1149  case V4L2_CID_EXPOSURE:
1150  memcpy(&ControlShutter_,&controls, sizeof(controls));
1151  break;
1152  case V4L2_CID_AUTOGAIN:
1153  memcpy(&ControlAutoGain_,&controls, sizeof(controls));
1154  break;
1155  }
1156  }
1157  // else
1158  // cout <<"control invalid: V4L2_CID_BASE+"<<controls.id-V4L2_CID_BASE<<endl;
1159  if(tmpID != controls.id){
1160  BIASERR("xioctl_ destroyed struct at ID: " << tmpID << " BaseID: " << V4L2_CID_BASE << " EndID: " << V4L2_CID_LASTP1 << " ID-BaseID: " << tmpID-V4L2_CID_BASE << endl);
1161  return -6;
1162  }
1163  }
1164 
1165  /* Damned f.... Logitech QC does not support these fine controls
1166 
1167  for (controls.id=V4L2_CID_CAMERA_CLASS_BASE; controls.id<=V4L2_CID_PRIVACY;
1168  controls.id++) {
1169  if (xioctl_(fd, (int)VIDIOC_QUERYCTRL, &controls)==0) {
1170  cout <<"control valid: "<<controls.id<<" name: "<<controls.name<<endl;
1171  switch (controls.id){
1172  case V4L2_CID_ZOOM_ABSOLUTE:
1173  cout <<"Have Control Zoom absolute"<<endl;
1174  memcpy(&ControlZoom_,&controls, sizeof(controls));
1175  break;
1176  case V4L2_CID_ZOOM_RELATIVE:
1177  cout <<"Have Control Zoom realtive"<<endl;
1178  break;
1179  case V4L2_CID_PAN_RESET:
1180  cout <<"Have Control pan reset "<<endl;
1181  memcpy(&ControlPanReset_,&controls, sizeof(controls));
1182  break;
1183  case V4L2_CID_TILT_RESET:
1184  cout <<"Have Control tilt reset "<<endl;
1185  memcpy(&ControlTiltReset_,&controls, sizeof(controls));
1186  break;
1187  case V4L2_CID_PAN_ABSOLUTE:
1188  cout <<"Have Control pan absolute"<<endl;
1189  break;
1190  case V4L2_CID_PAN_RELATIVE:
1191  cout <<"Have Control pan relative"<<endl;
1192  break;
1193  }
1194  }
1195  else
1196  cout <<"control invalid: V4L2_CID_CAMERA_CLASS_BASE +"<<controls.id-V4L2_CID_CAMERA_CLASS_BASE <<endl;
1197  }
1198  */
1199 
1200  format2_ = fmt;
1201  formatRGB_ = fmt;
1202  formatRGB_.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
1203  return 0;
1204 }
1205 
1206 
1207 #undef CLEAR
1208 
1210 SetGain(float g)
1211 {
1212  if (! CompleteInitialized_) return -1.0f;
1213  if (ControlGain_.id ==0) return -2.0f;
1214  struct v4l2_control ctrl;
1215  ctrl.id = ControlGain_.id;
1216 
1217  float min = ControlGain_.minimum;
1218  float max = ControlGain_.maximum;
1219  float val = (g /100.0f) * (max-min) + min;
1220  ctrl.value = (int) rint(val);
1221 
1222  if (xioctl_(fd, (int)VIDIOC_S_CTRL, &ctrl)<0) {
1223  perror("SetGain");
1224  return -3.0f;
1225  }
1226  else cout <<"Set Brightness to: "<<ctrl.value<<endl;
1227  return 0;
1228 }
1229 
1230 
1231 
1233 {
1234  if (! CompleteInitialized_) return -1.0f;
1235  if (ControlGain_.id ==0) return -2.0f;
1236  struct v4l2_control ctrl;
1237  ctrl.id = ControlGain_.id;
1238  if (xioctl_(fd, (int)VIDIOC_G_CTRL, &ctrl)<0) {
1239  perror("GetGain");
1240  return -3.0f;
1241  }
1242 
1243  cout <<"Gain val: "<<ctrl.value<<" min: "<<ControlGain_.minimum<<" max: "<<ControlGain_.maximum<<endl;
1244  float val = ctrl.value;
1245  float min = ControlGain_.minimum;
1246  float max = ControlGain_.maximum;
1247 
1248  val = ((val-min) / (max-min))*100.0f;
1249  return val;
1250 }
1251 
1252 void VideoSource_V4L::
1254 {
1255 }
1256 
1257 bool VideoSource_V4L::
1259 {
1260  return false;
1261 }
1262 
1263 void VideoSource_V4L::
1265 {
1266 }
1267 
1268 
1269 bool VideoSource_V4L::
1271 {
1272  return false;
1273 }
1274 
1277 {
1278  if (! CompleteInitialized_) return -1.0f;
1279  if (ControlBrightness_.id ==0) return -2.0f;
1280  struct v4l2_control ctrl;
1281  ctrl.id = ControlBrightness_.id;
1282 
1283  float min = ControlBrightness_.minimum;
1284  float max = ControlBrightness_.maximum;
1285  float val = (g/100.0f) * (max-min) + min;
1286  ctrl.value = (int) rint(val);
1287 
1288  if (xioctl_(fd, (int)VIDIOC_S_CTRL, &ctrl)<0) {
1289  perror("SetBrightness");
1290  return -3.0f;
1291  }
1292  return 0;
1293 }
1294 
1295 float VideoSource_V4L::
1297 {
1298  if (! CompleteInitialized_) return -1.0f;
1299  if (ControlBrightness_.id ==0) return -2.0f;
1300  struct v4l2_control ctrl;
1301  ctrl.id = ControlBrightness_.id;
1302  if (xioctl_(fd, (int)VIDIOC_G_CTRL, &ctrl)<0) {
1303  perror("GetBrightness");
1304  return -3.0f;
1305  }
1306 
1307  float val = ctrl.value;
1308  float min = ControlBrightness_.minimum;
1309  float max = ControlBrightness_.maximum;
1310  val = ((val-min) / (max-min))*100.0f;
1311  return val;
1312 }
1313 
1315 SetContrast(float g)
1316 {
1317  if (! CompleteInitialized_) return -1.0f;
1318  if (ControlContrast_.id ==0) return -2.0f;
1319  struct v4l2_control ctrl;
1320  ctrl.id = ControlContrast_.id;
1321 
1322  float min = ControlContrast_.minimum;
1323  float max = ControlContrast_.maximum;
1324  float val = (g/100.0f) * (max-min) + min;
1325  ctrl.value = (int) rint(val);
1326 
1327  if (xioctl_(fd, (int)VIDIOC_S_CTRL, &ctrl)<0) {
1328  perror("SetContrast");
1329  return -3.0f;
1330  }
1331  return 0;
1332 }
1333 
1334 
1335 float VideoSource_V4L::
1337 {
1338  if (! CompleteInitialized_) return -1.0f;
1339  if (ControlContrast_.id ==0) return -2.0f;
1340  struct v4l2_control ctrl;
1341  ctrl.id = ControlContrast_.id;
1342  if (xioctl_(fd, (int)VIDIOC_G_CTRL, &ctrl)<0) {
1343  perror("GetContrast");
1344  return -3.0f;
1345  }
1346  float val = ctrl.value;
1347  float min = ControlContrast_.minimum;
1348  float max = ControlContrast_.maximum;
1349 
1350  val = ((val-min) / (max-min))*100.0f;
1351  return val;
1352 }
1353 
1355 SetShutter(float g)
1356 {
1357  if (! CompleteInitialized_) return -1.0f;
1358  if (ControlShutter_.id ==0) return -2.0f;
1359  struct v4l2_control ctrl;
1360  ctrl.id = ControlShutter_.id;
1361 
1362  float min = ControlShutter_.minimum;
1363  float max = ControlShutter_.maximum;
1364  float val = (g/1.0f) * (max-min) + min;
1365  ctrl.value = (int) rint(val);
1366 
1367  if (xioctl_(fd, (int)VIDIOC_S_CTRL, &ctrl)<0) {
1368  perror("SetShutter");
1369  return -3.0f;
1370  }
1371  return 0;
1372 }
1373 
1374 
1375 float VideoSource_V4L::
1377 {
1378  if (! CompleteInitialized_) return -1.0f;
1379  if (ControlShutter_.id ==0) return -2.0f;
1380  struct v4l2_control ctrl;
1381  ctrl.id = ControlShutter_.id;
1382  if (xioctl_(fd, (int)VIDIOC_G_CTRL, &ctrl)<0) {
1383  perror("GetShutter");
1384  return -3.0f;
1385  }
1386  float val = ctrl.value;
1387  float min = ControlShutter_.minimum;
1388  float max = ControlShutter_.maximum;
1389 
1390  val = ((val-min) / (max-min))*1.0f;
1391  return val;
1392 
1393 }
1394 
1395 bool VideoSource_V4L::
1397 {
1398  return (ControlBrightness_.id !=0);
1399 }
1400 
1401 bool VideoSource_V4L::
1403 {
1404  return (ControlContrast_.id !=0);
1405 }
1406 
1407 bool VideoSource_V4L::
1409 {
1410  return (ControlShutter_.id !=0);
1411 }
1412 
1413 bool VideoSource_V4L::
1415 {
1416  return (ControlGain_.id !=0);
1417 }
1418 
1419 void VideoSource_V4L::
1421 {
1422 
1423 }
EColorModel
These are the most often used color models.
Definition: ImageBase.hh:127
YUYV422, 2 channels, full luminance Y, subsampled half U,V.
Definition: ImageBase.hh:133
virtual int InitImage(BIAS::ImageBase &Image)
float GetBrightness()
Get brightness as value in interval [0, 100]. */.
float GetContrast()
Get contrast as value in interval [0, 100]. */.
pthread_mutex_t ActiveFrameMutex_
Defines a common interface to different devices.
void GetDeviceChannelNames(std::vector< std::string > &names)
if more than one channel is present names can are returned here.
gray values, 1 channel
Definition: ImageBase.hh:130
bool IsControllable_
Must be initialized be the derived classes.
struct v4l2_buffer buffer_
bool IsEmpty() const
check if ImageData_ points to allocated image buffer or not
Definition: ImageBase.hh:245
void CopyIn_NoInit(void *data)
Take some data and fill it into the Image.
Definition: ImageBase.cpp:827
const char * DefaultDevice_
Device name.
unsigned int GetSizeByte() const
returns the nr.
Definition: ImageBase.hh:352
struct timeval GrabTime_
BIAS::ImageBase::EColorModel ColorMode_
Color mode used by camera.
int SetShutter(float g)
Set shutter (exposure time) in seconds.
std::vector< BIAS::Camera< unsigned char > > Frame_
int DeviceChannel_
Device channel.
struct v4l2_format formatRGB_
bool WaitForNew_
Wait for new frames in GrabSingle()
float BytesPerPixel_
BytesPerPixel cannot be int (e.g. it is 1.5 for YUV420p)
void ResetPanTiltZoom()
Reset digital zoom, pan and tilt to defaults to ensure compliance with calibration.
static int GetDirectoryContent(const std::string &Dir, const std::string &prefix, const std::string &suffix, std::vector< std::string > &content, const bool GetFullPath=false)
Read all files in.
float GetShutter()
Get shutter (exposure time) in seconds.
virtual int OpenDevice()
selects the first available device to open (e.g.
float GetGain()
Get gain in dB.
bool CompleteInitialized_
Complete_initialized_ is set when OpenDevice(), UseChannel() etc. are done.
int GetHeight() const
struct v4l2_queryctrl ControlContrast_
int Width_
Image format.
struct v4l2_queryctrl ControlShutter_
color values, 3 channels, order: blue,green,red
Definition: ImageBase.hh:132
int PreGrab()
Do last preparations before grabbing (e.g. start ISO transfer)
struct v4l2_queryctrl ControlAutoGain_
virtual int GrabSingle(BIAS::Camera< unsigned char > &image)
blocks until a new frame arrives from the cam, if dont want blocking set waitForNew() to false ...
Bayer_BGGR, 1 channel RGB image Bayer tile.
Definition: ImageBase.hh:146
int SetBrightness(float g)
Set brightness as value in interval [0, 100]. */.
int SetGain(float g)
Set gain in dB.
Bayer_GBRG, 1 channel RGB image Bayer tile.
Definition: ImageBase.hh:144
std::string Identifier_
Verbose camera descriptor.
struct v4l2_format format2_
int GetAllDevices(std::vector< std::string > &devices)
bool Grabbing_
Grabbing flag is set and unset in GrabSingle() methods.
BIAS::JpegHandler Decompressor_
std::map< std::string, std::string > ModelNameToDevice_
color values, 3 channels, order: red,green,blue
Definition: ImageBase.hh:131
void SetDebugLevel(const long int lv)
Definition: Debug.hh:318
int Decompress(BIAS::Image< unsigned char > &destImg, bool readComment=false)
Start decompression of previously given data (from ReadJPEG() or SetCompressedData()), results will be stored in destination image.
UYVY422, 2 channels, full luminance Y, subsampled half U,V inverse order.
Definition: ImageBase.hh:134
struct v4l2_queryctrl ControlBrightness_
bool Active_
Active flag is set in PreGrab() und unset in PostGrab()
struct v4l2_queryctrl ControlGain_
int SetContrast(float g)
Set contrast as value in interval [0, 100]. */.
void InvalidateUID()
sets the image&#39;s uid to invalid
Definition: ImageBase.hh:597
BIAS::Camera< unsigned char > jpegImg_
const StorageType * GetImageData() const
overloaded GetImageData() from ImageBase
Definition: Image.hh:137
void SetUID(const BIAS::UUID &id)
Definition: ImageBase.hh:589
void AddMode(unsigned int width, unsigned int height, float fps, ImageBase::EColorModel colormodel, bool interlaced=false)
void SetCompressedData(void *data, long length)
Copy memory area in which compressed data can be found and set its length in byte.
std::vector< std::string > deviceChannelNames_
int Init(long size=10485760)
Initialize object with standard values and limit shared memory area to given size (in byte...
invalid (not set) image format
Definition: ImageBase.hh:129
Checks for VideoSource capabilities.
struct v4l2_capability capability2
void SetTime(unsigned long long int sec, unsigned long long int usec)
Set time and ensure correct format (seconds and useconds after &#39;sec&#39;)
Definition: Camera.hh:124
void SetName(const std::string &name)
This class extends VideoSource for the use of Video4Linux supported devices like framegrabber, USB cameras.
int PostGrab()
Stop anything started in PreGrab()
int GetCapabilities(VideoSourceCapabilities &caps)
Use this method to learn something about the capabilities of the source (only useful for V4L sources...
static UUID GenerateUUID(const bool &consecutively=DEFAULT_UUID_CONSECUTIVELY)
static function which simply produces a uuid and returns
Definition: UUID.cpp:235
std::vector< struct buffer > Buffers_
static void * GrabContThread_(void *arg)
BGRA color values, 4 channels, order: blue,green,red,alpha.
Definition: ImageBase.hh:150