• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

src/F2/V4L2Sensor.cpp

00001 #include <asm/types.h>
00002 #include <sys/types.h>
00003 #include <sys/syscall.h>
00004 #include <sys/prctl.h>
00005 #include <linux/capability.h>
00006 
00007 #include <pthread.h>
00008 #include <poll.h>
00009 
00010 #include <stdio.h>
00011 #include <stdlib.h>
00012 #include <string.h>
00013 #include <unistd.h>
00014 #include <math.h>
00015 
00016 #include <sys/fcntl.h>
00017 #include <sys/ioctl.h>
00018 #include <sys/mman.h>
00019 #include <sys/time.h>
00020 #include <time.h>
00021 
00022 #include <errno.h>
00023 #include <malloc.h>
00024 #include <linux/videodev2.h>
00025 
00026 #include "../Debug.h"
00027 #include "FCam/Event.h"
00028 #include "V4L2Sensor.h"
00029 #warning make sure to point isp_user to the right place before long!
00030 #include "/elphel/git/linux-omap-2.6/drivers/media/video/isp/isp_user.h"
00031 //#include "/elphel/git/linux-omap-2.6/arch/arm/plat-omap/include/mach/isp_user.h"
00032 //#include "linux/isp_user.h"
00033 
00034 namespace FCam { namespace F2 {
00035 
00036     V4L2Sensor *V4L2Sensor::instance(std::string fname) {
00037         std::map<std::string, V4L2Sensor *>::iterator i;
00038         i = instances_.find(fname);
00039         if (i == instances_.end()) {
00040             instances_[fname] = new V4L2Sensor(fname);            
00041         }
00042 
00043         return instances_[fname];
00044     };
00045 
00046     V4L2Sensor::V4L2Sensor(std::string fname) : state(CLOSED), filename(fname) {
00047         
00048     }
00049 
00050     std::map<std::string, V4L2Sensor *> V4L2Sensor::instances_;
00051 
00052     void V4L2Sensor::open() {
00053         if (state != CLOSED) {
00054             printf("Sensor is already open!\n");
00055             return;
00056         }
00057 
00058         fd = ::open(filename.c_str(), O_RDWR | O_NONBLOCK, 0);
00059     
00060         if (fd < 0) {
00061             error(Event::DriverError,"V4L2Sensor: Error opening device %s: %s", filename.c_str(), strerror(errno));
00062             return;
00063         }
00064     
00065         state = IDLE;
00066     }
00067 
00068     void V4L2Sensor::close() {
00069         switch(state) {
00070         case STREAMING:
00071             stopStreaming();
00072         case IDLE:
00073             ::close(fd);
00074         case CLOSED:
00075             break;
00076         }
00077         state = CLOSED;
00078     }
00079 
00080     int V4L2Sensor::getFD() {
00081         if (state == CLOSED) {
00082             return -1;
00083         }
00084         return fd;
00085     }
00086 
00087     void V4L2Sensor::startStreaming(Mode m, 
00088                                     const HistogramConfig &histogram,
00089                                     const SharpnessMapConfig &sharpness) {
00090         
00091         if (state != IDLE) {
00092             printf("Can only initiate streaming if sensor is idle\n");
00093             return;
00094         }
00095 
00096         struct v4l2_format fmt;
00097         
00098         memset(&fmt, 0, sizeof(struct v4l2_format));
00099         
00100         fmt.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00101         fmt.fmt.pix.width       = m.width;
00102         fmt.fmt.pix.height      = m.height;
00103         if (m.type == UYVY) {
00104             fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
00105         } else if (m.type == RAW) {
00106             fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SGRBG10;
00107         } else {
00108             error(Event::InternalError, "V4L2Sensor: Unknown image format requested");
00109             return;
00110         }
00111         fmt.fmt.pix.field       = V4L2_FIELD_NONE;
00112 
00113         // Request format
00114         if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) {
00115             error(Event::DriverError,"VIDIOC_S_FMT: %s", strerror(errno));
00116             return;
00117         }
00118     
00119         currentMode.width = fmt.fmt.pix.width;
00120         currentMode.height = fmt.fmt.pix.height;
00121         currentMode.type = (fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY) ? UYVY : RAW;
00122 
00123         struct v4l2_requestbuffers req;    
00124         memset(&req, 0, sizeof(req));
00125         req.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00126         req.memory = V4L2_MEMORY_MMAP;
00127         req.count  = 8;
00128 
00129         if (ioctl(fd, VIDIOC_REQBUFS, &req) < 0) {
00130             error(Event::DriverError,"VIDIOC_REQBUFS: %s", strerror(errno));
00131             return;
00132         } 
00133 
00134         buffers.resize(req.count);
00135 
00136         for (size_t i = 0; i < buffers.size(); i++) {
00137             v4l2_buffer buf;
00138             memset(&buf, 0, sizeof(v4l2_buffer));
00139             buf.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00140             buf.memory = V4L2_MEMORY_MMAP;
00141             buf.index  = i;
00142 
00143             if (ioctl(fd, VIDIOC_QUERYBUF, &buf) < 0) {
00144                 error(Event::DriverError,"VIDIOC_QUERYBUF: %s", strerror(errno));
00145                 return;
00146             }
00147         
00148             buffers[i].index = i;
00149             buffers[i].length = buf.length;
00150             buffers[i].data = 
00151                 (unsigned char *)mmap(NULL, buffers[i].length, PROT_READ | PROT_WRITE,
00152                                       MAP_SHARED, fd, buf.m.offset);
00153         
00154             if (buffers[i].data == MAP_FAILED) {
00155                 error(Event::InternalError, "V4L2Sensor: mmap failed: %s", strerror(errno));
00156                 return;
00157             }
00158         }   
00159 
00160         for (size_t i = 0; i < buffers.size(); i++) {
00161             releaseFrame(&buffers[i]);
00162         }
00163 
00164         // set the starting parameters
00165         setHistogramConfig(histogram);
00166         setSharpnessMapConfig(sharpness);
00167 
00168         enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00169         if (ioctl(fd, VIDIOC_STREAMON, &type) < 0) {
00170             error(Event::DriverError,"VIDIOC_STREAMON: %s", strerror(errno));
00171             return;
00172         }
00173         
00174         dprintf(DBG_MAJOR, "Sensor now streaming\n");
00175         state = STREAMING;
00176     }
00177 
00178 
00179     void V4L2Sensor::stopStreaming() {
00180         if (state != STREAMING) {
00181             printf("Camera is already not streaming!\n");
00182             return;
00183         }
00184 
00185         enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00186         if (ioctl(fd, VIDIOC_STREAMOFF, &type) < 0) {
00187             error(Event::DriverError,"VIDIOC_STREAMOFF: %s", strerror(errno));
00188             return;
00189         }
00190 
00191         for (size_t i = 0; i < buffers.size(); i++) {
00192             if (munmap(buffers[i].data, buffers[i].length)) {
00193                 error(Event::InternalError, "V4L2Sensor: munmap failed: %s", strerror(errno));
00194             }
00195         }
00196 
00197         state = IDLE;
00198     }
00199 
00200 
00201 
00202     V4L2Sensor::V4L2Frame *V4L2Sensor::acquireFrame(bool blocking) {
00203         if (state != STREAMING) {
00204             printf("Can't acquire a frame when not streaming!\n");
00205             return NULL;
00206         }
00207 
00208         //printf("Acquiring frame...\n"); fflush(stdout);
00209         
00210         v4l2_buffer buf;
00211         memset(&buf, 0, sizeof(v4l2_buffer));
00212         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00213         buf.memory = V4L2_MEMORY_MMAP;
00214         
00215         if (blocking) {
00216             struct pollfd p = {fd, POLLIN, 0};
00217             poll(&p, 1, -1);
00218             if (!(p.revents & POLLIN)) {
00219                 error(Event::DriverError,"Poll returned without data being available: %s", strerror(errno));
00220                 return NULL;
00221             }
00222         }    
00223         
00224         if (ioctl(fd, VIDIOC_DQBUF, &buf) < 0) {
00225             if (errno == EAGAIN && !blocking) {
00226                 return NULL;
00227             }
00228             
00229             error(Event::DriverError,"VIDIOC_DQBUF: %s", strerror(errno));
00230             return NULL;
00231         }
00232 
00233 
00234         buffers[buf.index].processingDoneTime = Time(buf.timestamp);
00235         return &(buffers[buf.index]);
00236     }
00237 
00238 
00239 
00240     Histogram V4L2Sensor::getHistogram(Time t, const HistogramConfig &conf) {
00241 
00242         //printf("Buffer timestamp: %d %d\n", t.s(), t.us());
00243         if (!conf.enabled) {
00244             return Histogram();
00245         }
00246 
00247         // grab the histogram data for this frame
00248         struct isp_hist_data hist_data;
00249         unsigned buf[64 * 4];  // Hardcoded for OMAP3 ISP histogram (64 buckets, 4 channels)
00250         Time h;
00251         int tries = 3;
00252         while (--tries > 0) {
00253             hist_data.hist_statistics_buf = buf;
00254             hist_data.update = REQUEST_STATISTICS;
00255             
00256             // For now we assume acquire_frame is being called quickly
00257             // enough that only the newest frame is relevant
00258             hist_data.frame_number = NEWEST_FRAME;
00259             hist_data.curr_frame = 0;
00260             hist_data.config_counter = 0;
00261             hist_data.ts.tv_sec = 0;
00262             hist_data.ts.tv_usec = 0;
00263             
00264             if (ioctl(fd, VIDIOC_PRIVATE_ISP_HIST_REQ, &hist_data)) {
00265                 error(Event::DriverError, "V4L2Sensor::getHistogram: VIDIOC_PRIVATE_ISP_HIST_REQ: %s\n",strerror(errno));
00266                 return Histogram();
00267             }          
00268         
00269             // TODO: Deal with timestamps that are too early or too late
00270             
00271             h = Time(hist_data.ts);        
00272             
00273             if ((t - h) < 6000) {
00274                 break;
00275             }
00276             usleep(10000);
00277         }
00278         if (tries != 2) dprintf(DBG_MINOR, "V4L2Sensor::getHistogram: Waited for the histogram %d times\n", 2-tries);
00279         if (!tries) {
00280             error(Event::DriverError, "Histogram cannot be found\n");
00281             return Histogram();
00282         }
00283         
00284          while ((t-h) < -4000) {
00285              // we got the wrong histogram!
00286              if (hist_data.frame_number == 0) hist_data.frame_number = 4095;
00287              else hist_data.frame_number--;
00288 
00289              if (ioctl(fd, VIDIOC_PRIVATE_ISP_HIST_REQ, &hist_data)) {
00290                 error(Event::DriverError, "V4L2Sensor::getHistogram: VIDIOC_PRIVATE_ISP_HIST_REQ: %s\n", strerror(errno));
00291                 return Histogram();
00292              }          
00293 
00294              h = Time(hist_data.ts);
00295          }
00296         Histogram hist(64, 3, conf.region);
00297         for (int i = 0; i < 64; i++) {
00298             hist(i, 0) = buf[64 + i];  // r
00299             hist(i, 1) = buf[i];       // g
00300             hist(i, 2) = buf[128 + i]; // b
00301         }
00302         return hist;
00303     }
00304 
00305     SharpnessMap V4L2Sensor::getSharpnessMap(Time t, const SharpnessMapConfig &conf) {    
00306         if (!conf.enabled) {
00307             return SharpnessMap();
00308         }
00309 
00310         // grab the sharpness map for this frame        
00311         struct isp_af_data af_data;
00312         af_data.frame_number = NEWEST_FRAME;
00313         af_data.update = REQUEST_STATISTICS;
00314         af_data.curr_frame = 0;
00315         af_data.config_counter = 0;
00316         af_data.xtrastats.ts.tv_sec = 0;
00317         af_data.xtrastats.ts.tv_usec = 0;
00318         unsigned buf[16*12*12]; // Hardcoded for OMAP3 ISP size
00319         af_data.af_statistics_buf = buf;
00320         
00321         if (ioctl(fd, VIDIOC_PRIVATE_ISP_AF_REQ, &af_data)) {
00322             error(Event::DriverError, "V4L2Sensor::getSharpnessMap: VIDIOC_PRIVATE_ISP_AF_REQ: %s\n", strerror(errno) );
00323             return SharpnessMap();
00324         }          
00325 
00326         Time s(af_data.xtrastats.ts);        
00327         if ((t - s) > 6000) {
00328             warning(Event::DriverError, "Missing sharpness: (%d)\n", t-s );
00329         }
00330 
00331         while ((t-s) < -2000) {
00332             // we got the wrong sharpness map
00333             if (af_data.frame_number == 0) af_data.frame_number = 4095;
00334             else af_data.frame_number--;
00335 
00336             if (ioctl(fd, VIDIOC_PRIVATE_ISP_AF_REQ, &af_data)) {
00337                 error(Event::DriverError, "V4L2Sensor::getSharpnessMap: VIDIOC_PRIVATE_ISP_AF_REQ: %s\n", strerror(errno) );
00338                 return SharpnessMap();
00339             }          
00340             s = Time(af_data.xtrastats.ts);
00341         }
00342         SharpnessMap m(Size(16,12), 3);
00343         unsigned *bufPtr = &buf[0];
00344         for (int y = 0; y < m.size().height; y++) {
00345             for (int x = 0; x < m.size().width; x++) {
00346                 m(x, y, 0) = bufPtr[1];
00347                 m(x, y, 1) = bufPtr[5];
00348                 m(x, y, 2) = bufPtr[9];
00349                 bufPtr += 12;
00350             }
00351         }
00352 
00353         return m;
00354     }
00355 
00356     void V4L2Sensor::setHistogramConfig(const HistogramConfig &histogram) {       
00357         if (!histogram.enabled) return;
00358 
00359          // get the output size from the ccdc
00360          isp_pipeline_stats pstats;
00361          if (ioctl(fd, VIDIOC_PRIVATE_ISP_PIPELINE_STATS_REQ, &pstats) < 0) {
00362             error(Event::DriverError, "V4L2Sensor::setHistogramConfig: VIDIOC_PRIVATE_ISP_PIPELINE_STATS_REQ: %s\n", strerror(errno));
00363              return;
00364          }
00365                 
00366          dprintf(4, "CCDC output: %d x %d\n", pstats.ccdc_out_w, pstats.ccdc_out_h);
00367          dprintf(4, "PRV  output: %d x %d\n", pstats.prv_out_w, pstats.prv_out_h);
00368          dprintf(4, "RSZ  input:  %d x %d + %d, %d\n",
00369                 pstats.rsz_in_w, pstats.rsz_in_h,
00370                 pstats.rsz_in_x, pstats.rsz_in_y);
00371          dprintf(4, "RSZ  output: %d x %d\n", pstats.rsz_out_w, pstats.rsz_out_h);
00372         
00373         struct isp_hist_config hist_cfg;                       
00374         hist_cfg.enable = 1;
00375         hist_cfg.source = HIST_SOURCE_CCDC;
00376         hist_cfg.input_bit_width = 10;
00377         hist_cfg.num_acc_frames = 1;
00378         hist_cfg.hist_bins = HIST_BINS_64;
00379         hist_cfg.cfa = HIST_CFA_BAYER;
00380         // set the gains to slightly above 1 in 3Q5 format, in
00381         // order to use the full range in the histogram. Without
00382         // this, bucket #60 is saturated pixels, and 61-64 are
00383         // unused.
00384         hist_cfg.wg[0] = 35;
00385         hist_cfg.wg[1] = 35;
00386         hist_cfg.wg[2] = 35;
00387         hist_cfg.wg[3] = 35;
00388         hist_cfg.num_regions = 1;
00389         
00390         // set up its width and height
00391         unsigned x = ((unsigned)histogram.region.x * pstats.ccdc_out_w) / currentMode.width;
00392         unsigned y = ((unsigned)histogram.region.y * pstats.ccdc_out_h) / currentMode.height;
00393         unsigned w = ((unsigned)histogram.region.width * pstats.ccdc_out_w) / currentMode.width;
00394         unsigned h = ((unsigned)histogram.region.height * pstats.ccdc_out_h) / currentMode.height;
00395         if (x > pstats.ccdc_out_w) x = pstats.ccdc_out_w-1;
00396         if (y > pstats.ccdc_out_h) y = pstats.ccdc_out_h-1;
00397         if (w > pstats.ccdc_out_w) w = pstats.ccdc_out_w-x;
00398         if (h > pstats.ccdc_out_h) h = pstats.ccdc_out_h-y;
00399         hist_cfg.reg_hor[0] = (x << 16) | w;
00400         hist_cfg.reg_ver[0] = (y << 16) | h;
00401         dprintf(4, "Histogram size: %d x %d + %d, %d\n", w, h, x, y);
00402         
00403         dprintf(DBG_MINOR, "Enabling histogram generator\n");
00404         // enable the histogram generator
00405         if (ioctl(fd, VIDIOC_PRIVATE_ISP_HIST_CFG, &hist_cfg)) {
00406             error(Event::DriverError, "VIDIOC_PRIVATE_ISP_HIST_CFG: %s", strerror(errno));
00407             return;
00408         }
00409 
00410         currentHistogram = histogram;
00411         currentHistogram.buckets = 64;
00412     }
00413 
00414     void V4L2Sensor::setSharpnessMapConfig(const SharpnessMapConfig &sharpness) {       
00415         if (!sharpness.enabled) return;
00416 
00417         // Ignore the requested size and use 16x12
00418         Size size = Size(16, 12);
00419 
00420         // get the output size from the ccdc
00421         isp_pipeline_stats pstats;
00422         if (ioctl(fd, VIDIOC_PRIVATE_ISP_PIPELINE_STATS_REQ, &pstats) < 0) {
00423             error(Event::DriverError, "VIDIOC_PRIVATE_ISP_PIPELINE_STATS_REQ: %s", strerror(errno));
00424             return;
00425         }
00426    
00427         struct af_configuration af_config;
00428         
00429         af_config.alaw_enable = H3A_AF_ALAW_DISABLE;
00430         af_config.hmf_config.enable = H3A_AF_HMF_ENABLE;
00431         af_config.hmf_config.threshold = 10;
00432         af_config.rgb_pos = RG_GB_BAYER;
00433         af_config.iir_config.hz_start_pos = 0;
00434         
00435         // The IIR coefficients are as follows (yay reverse-engineering!)
00436         
00437         // The format is S6Q5 fixed point. A positive value of x
00438         // should be written as 32*x. A negatives value of x
00439         // should be written as 4096 - 32*x
00440         
00441         // 0: global gain? not sure.
00442         // 1-2: IIR taps on the first biquad
00443         // 3-5: FIR taps on the first biquad
00444         // 6-7: IIR taps on the second biquad
00445         // 8-10: FIR taps on the second biquad            
00446         
00447         // A high pass filter aimed at ~8 pixel frequencies and above
00448         af_config.iir_config.coeff_set0[0] = 32; // gain of 1
00449         
00450         af_config.iir_config.coeff_set0[1] = 4096-27;
00451         af_config.iir_config.coeff_set0[2] = 6;
00452         
00453         af_config.iir_config.coeff_set0[3] = 16;
00454         af_config.iir_config.coeff_set0[4] = 4096-32;
00455         af_config.iir_config.coeff_set0[5] = 16;
00456         
00457         af_config.iir_config.coeff_set0[6] = 0;
00458         af_config.iir_config.coeff_set0[7] = 0;
00459         
00460         af_config.iir_config.coeff_set0[8] = 32;
00461         af_config.iir_config.coeff_set0[9] = 0;
00462         af_config.iir_config.coeff_set0[10] = 0;
00463         
00464         
00465         // A high pass filter aimed at ~4 pixel frequencies and above
00466         af_config.iir_config.coeff_set1[0] = 32; // gain of 1
00467         
00468         af_config.iir_config.coeff_set1[1] = 0;
00469         af_config.iir_config.coeff_set1[2] = 0;
00470         
00471         af_config.iir_config.coeff_set1[3] = 16;
00472         af_config.iir_config.coeff_set1[4] = 4096-32;
00473         af_config.iir_config.coeff_set1[5] = 16;
00474         
00475         af_config.iir_config.coeff_set1[6] = 0;
00476         af_config.iir_config.coeff_set1[7] = 0;
00477         
00478         af_config.iir_config.coeff_set1[8] = 32;
00479         af_config.iir_config.coeff_set1[9] = 0;
00480         af_config.iir_config.coeff_set1[10] = 0;
00481         
00482         af_config.mode = ACCUMULATOR_SUMMED;
00483         af_config.af_config = H3A_AF_CFG_ENABLE;
00484         int paxWidth = ((pstats.ccdc_out_w-4) / (2*size.width))*2;
00485         int paxHeight = ((pstats.ccdc_out_h-4) / (2*size.height))*2;
00486 
00487         if (paxWidth > 256) {
00488             error(Event::InternalError, "AF paxels are too wide. Use a higher resolution sharpness map\n");
00489             return;
00490         }
00491         if (paxHeight > 256) {
00492             error(Event::InternalError, "AF paxels are too tall. Use a higher resolution sharpness map\n");
00493             return;
00494         }
00495         if (paxWidth < 16) {            
00496             error(Event::InternalError, "AF paxels are too narrow. Use a lower resolution sharpness map\n");
00497             return;
00498         }
00499         if (paxHeight < 2) {
00500             error(Event::InternalError, "AF paxels are too short. Use a lower resolution sharpness map\n");
00501             return;
00502         }
00503         
00504         dprintf(4, "V4L2Sensor::setSharpnessMapConfig: Using %d x %d paxels for af\n", paxWidth, paxHeight);
00505         af_config.paxel_config.width = (paxWidth-2)/2;
00506         af_config.paxel_config.height = (paxHeight-2)/2;
00507         af_config.paxel_config.hz_start = (pstats.ccdc_out_w - size.width * paxWidth)/2;
00508         af_config.paxel_config.vt_start = (pstats.ccdc_out_h - size.height * paxHeight)/2;
00509         af_config.paxel_config.hz_cnt = size.width-1;
00510         af_config.paxel_config.vt_cnt = size.height-1;
00511         af_config.paxel_config.line_incr = 0;            
00512         
00513         dprintf(DBG_MINOR, "Enabling sharpness detector\n");
00514         if (ioctl(fd, VIDIOC_PRIVATE_ISP_AF_CFG, &af_config)) {
00515             error(Event::DriverError, "VIDIOC_PRIVATE_ISP_AF_CFG: %s", strerror(errno));
00516             return;
00517         }
00518 
00519         currentSharpness = sharpness;
00520     }
00521 
00522     void V4L2Sensor::releaseFrame(V4L2Frame *frame) {
00523         //printf("Releasing frame %d\n", frame->index); fflush(stdout);
00524 
00525         //usleep(1000);
00526         
00527         // requeue the buffer
00528         v4l2_buffer buf;
00529         memset(&buf, 0, sizeof(v4l2_buffer));
00530         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00531         buf.memory = V4L2_MEMORY_MMAP;
00532         buf.index = frame->index;
00533         
00534         if (ioctl(fd, VIDIOC_QBUF, &buf) < 0) {
00535             error(Event::DriverError, "VIDIOC_QBUF: %s", strerror(errno));
00536             return;
00537         }
00538     }
00539    
00540     void V4L2Sensor::setControl(unsigned int id, int value) {
00541         if (state == CLOSED) return;
00542         v4l2_control ctrl;
00543         ctrl.id = id;
00544         ctrl.value = value;
00545         if (ioctl(fd, VIDIOC_S_CTRL, &ctrl) < 0) {
00546             // TODO: Better error reporting for all the get/set
00547             error(Event::DriverError, "VIDIOC_S_CTRL: %s", strerror(errno));
00548             return;
00549         }
00550     }
00551 
00552     int V4L2Sensor::getControl(unsigned int id) {
00553         if (state == CLOSED) return -1;
00554         v4l2_control ctrl;
00555         ctrl.id = id;
00556         if (ioctl(fd, VIDIOC_G_CTRL, &ctrl) < 0) {
00557             error(Event::DriverError, "VIDIOC_G_CTRL: %s", strerror(errno));
00558             return -1;
00559         }
00560 
00561         return ctrl.value;
00562     }
00563 
00564     void V4L2Sensor::setExposure(int e) {
00565         if (state == CLOSED) return;
00566 
00567         struct v4l2_control ctrl;
00568         ctrl.id = V4L2_CID_EXPOSURE;
00569         ctrl.value = e;
00570         if (ioctl(fd, VIDIOC_S_CTRL, &ctrl) < 0) {
00571             error(Event::DriverError,"VIDIOC_S_CTRL: %s", strerror(errno));
00572             return;
00573         }       
00574         
00575     }
00576 
00577     int V4L2Sensor::getExposure() {
00578         if (state == CLOSED) return -1;        
00579 
00580         struct v4l2_control ctrl;
00581         ctrl.id = V4L2_CID_EXPOSURE;
00582         
00583         if (ioctl(fd, VIDIOC_G_CTRL, &ctrl) < 0) {
00584             error(Event::DriverError,"VIDIOC_G_CTRL: %s", strerror(errno));
00585             return -1;
00586         }       
00587         
00588         return ctrl.value;
00589     }
00590 
00591 #define V4L2_CID_FRAME_TIME (V4L2_CTRL_CLASS_CAMERA | 0x10ff)
00592 
00593     void V4L2Sensor::setFrameTime(int e) {
00594         if (state == CLOSED) return;
00595         
00596         struct v4l2_control ctrl;
00597         ctrl.id = V4L2_CID_FRAME_TIME;
00598         ctrl.value = e;
00599         if (ioctl(fd, VIDIOC_S_CTRL, &ctrl) < 0) {
00600             error(Event::DriverError,"VIDIOC_S_CTRL: %s", strerror(errno));
00601             return;
00602         }       
00603     }
00604 
00605     int V4L2Sensor::getFrameTime() {
00606         if (state == CLOSED) return -1;        
00607 
00608         struct v4l2_control ctrl;
00609         ctrl.id = V4L2_CID_FRAME_TIME;
00610         
00611         if (ioctl(fd, VIDIOC_G_CTRL, &ctrl) < 0) {
00612             error(Event::DriverError,"VIDIOC_G_CTRL: %s", strerror(errno));
00613             return -1;
00614         }       
00615         
00616         return ctrl.value;
00617     }
00618 
00619     void V4L2Sensor::setGain(float g) {
00620         if (state == CLOSED) return;
00621 
00622         unsigned int gain;
00623         struct v4l2_control ctrl;
00624         
00625         gain = (int)(g * 32.0 + 0.5);
00626         
00627         ctrl.id = V4L2_CID_GAIN;
00628         ctrl.value = gain;
00629         if (ioctl(fd, VIDIOC_S_CTRL, &ctrl) < 0) {
00630             error(Event::DriverError,"VIDIOC_S_CTRL: %s", strerror(errno));
00631             return;
00632         }              
00633     }
00634 
00635     float V4L2Sensor::getGain() {
00636         if (state == CLOSED) return -1.0f;
00637 
00638         struct v4l2_control ctrl;
00639         
00640         ctrl.id = V4L2_CID_GAIN;
00641         if (ioctl(fd, VIDIOC_G_CTRL, &ctrl) < 0) {
00642             error(Event::DriverError,"VIDIOC_G_CTRL: %s", strerror(errno));
00643             return -1.0f;
00644         }       
00645         
00646         return ctrl.value / 32.0f;    
00647     }
00648 }}
00649 
00650 

Generated on Fri Sep 24 2010 15:53:00 for FCam by  doxygen 1.7.1