Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

CameraDriverV4L2.cc

Go to the documentation of this file.
00001 #ifdef __linux__
00002 
00003 #include "CameraDriverV4L2.h"
00004 #include "Shared/debuget.h"
00005 //#include "Shared/TimeET.h"
00006 #include "Shared/MarkScope.h"
00007 
00008 #include <fcntl.h>
00009 #include <sys/ioctl.h>
00010 #include <sys/mman.h>
00011 #include <sys/types.h>
00012 #include <sys/time.h>
00013 #include <unistd.h>
00014 #include <errno.h>
00015 
00016 using namespace std; 
00017 
00018 const std::string CameraDriverV4L2::autoRegisterCameraDriverV4L2 = DeviceDriver::getRegistry().registerType<CameraDriverV4L2>("Camera");
00019 
00020 bool CameraDriverV4L2::advance()
00021 {
00022   //cout << "CDV4L2: getData called with timestamp " << timestamp << "\n";
00023 
00024   int ret;
00025 
00026   if (camfd < 0)
00027     return false;
00028 
00029   //std::cout << get_time() << " start" << std::endl;
00030   MarkScope l(lock);
00031 
00032   // enable streaming if it hasn't been yet
00033   if (!streaming) {
00034     if (video_enable()) {
00035       return false;
00036     }
00037   }
00038 
00039   //std::cout << get_time() << " getting sample" << std::endl;
00040   // clear out single buffer
00041   ret = dequeue_buffer();
00042   if (ret < 0 && errno!= EAGAIN) {
00043     return false;
00044   }
00045   
00046   timestamp = get_time();
00047   //std::cout << timestamp << " have sample " << ret << std::endl;
00048   
00049 
00050   if (downsample)
00051     downsample_yuyv();
00052   else
00053     upsample_yuyv();
00054   
00055   //std::cout << get_time() << " done" << std::endl;
00056 
00057   ++frameCount;
00058   return true;
00059 }
00060 
00061 int CameraDriverV4L2::dequeue_buffer()
00062 {
00063   int ret;
00064   
00065   // dequeue an available buffer
00066   memset( &v_buf, 0, sizeof (struct v4l2_buffer) );
00067   v_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00068   v_buf.memory = V4L2_MEMORY_MMAP;
00069   ret = ioctl( camfd, VIDIOC_DQBUF, &v_buf );
00070   if (ret) {
00071     perror("Unable to dequeue buffer");
00072     return ret;
00073   }
00074   
00075   // print some stuff out for now
00076   //    cout << "CDV4L2: Buffer " << v_buf.index << " dequeued. Capture time: " << v_buf.timestamp.tv_sec << "s, sequence num "
00077   //   << v_buf.sequence << ".\n";
00078   //    cout << "CDV4L2: Buffer contains " << v_buf.bytesused << " bytes in buffer of length " << v_buf.length << ".\n"; 
00079 
00080   // resize if needed (might move this)
00081   if (captureBuf.size() != v_buf.length)
00082     captureBuf.resize(v_buf.length);
00083 
00084   // copy the frame over
00085   memcpy(&captureBuf[0], v_mem[v_buf.index].start, v_buf.bytesused);
00086   
00087   // requeue the buffer
00088   ret = ioctl( camfd, VIDIOC_QBUF, &v_buf);
00089   if (ret < 0) {
00090     perror("Unable to requeue buffer");
00091     return ret;
00092   }
00093   
00094   return 0;
00095 }
00096 
00097 void CameraDriverV4L2::registerSource() {
00098   open_cam();
00099   path.addPrimitiveListener(this);
00100   resolution.addPrimitiveListener(this);
00101   queryOptions.addPrimitiveListener(this);
00102   userOptions.addCollectionListener(this);
00103   for(plist::DictionaryOf< plist::Primitive<int> >::const_iterator it=userOptions.begin(); it!=userOptions.end(); ++it)
00104     it->second->addPrimitiveListener(this);
00105 }
00106 
00107 void CameraDriverV4L2::deregisterSource() {
00108   userOptions.removeCollectionListener(this);
00109   for(plist::DictionaryOf< plist::Primitive<int> >::const_iterator it=userOptions.begin(); it!=userOptions.end(); ++it)
00110     it->second->removePrimitiveListener(this);
00111   queryOptions.removePrimitiveListener(this);
00112   resolution.removePrimitiveListener(this);
00113   path.removePrimitiveListener(this);
00114   close_cam();
00115 }
00116 
00117 void CameraDriverV4L2::doUnfreeze() {
00118   thread.start();
00119 }
00120 
00121 void CameraDriverV4L2::doFreeze() {
00122   if(thread.isStarted())
00123     thread.stop().join();
00124 }
00125 
00126 void CameraDriverV4L2::threadrun() {
00127   while(advance())
00128     Thread::testCurrentCancel();
00129 }
00130 
00131 
00132 void CameraDriverV4L2::plistValueChanged(const plist::PrimitiveBase& pl)
00133 {
00134   if (&pl == &path || &pl == &resolution) {
00135     MarkScope l(lock);
00136     open_cam();
00137   }
00138   else if (&pl == &queryOptions && queryOptions == true) {
00139     MarkScope l(lock);
00140     query_options(true);
00141     queryOptions = false;
00142   }
00143   else {
00144     // first find name in userOptions
00145     std::string name;
00146     for(plist::DictionaryOf< plist::Primitive<int> >::const_iterator it=userOptions.begin(); it!=userOptions.end(); ++it) {
00147       if(&pl == it->second) {
00148         name = it->first;
00149         break;
00150       }
00151     }
00152     if(name.size()==0) {
00153       std::cerr << "Could not find name for modified value" << std::endl;
00154       return;
00155     }
00156 
00157     // We verified a proper name was set, to apply reopen camera.
00158     // we could call setControl directly, but this seems to block
00159     // for random and significant amounts of time if video capture is active
00160     MarkScope l(lock);
00161     close_cam();
00162     open_cam(); // we only have listeners if camera should be active
00163   }
00164 }
00165 
00166 void CameraDriverV4L2::plistCollectionEntryAdded(plist::Collection& /*col*/, plist::ObjectBase& obj) {
00167   plist::PrimitiveBase& prim = dynamic_cast<plist::PrimitiveBase&>(obj);
00168   prim.addPrimitiveListener(this);
00169   plistValueChanged(prim);
00170 }
00171 void CameraDriverV4L2::plistCollectionEntryRemoved(plist::Collection& /*col*/, plist::ObjectBase& obj) {
00172   plist::PrimitiveBase& prim = dynamic_cast<plist::PrimitiveBase&>(obj);
00173   prim.removePrimitiveListener(this);
00174 }
00175 void CameraDriverV4L2::plistCollectionEntriesChanged(plist::Collection& /*col*/) {
00176   // reapplies all settings, just close and open camera
00177   MarkScope l(lock);
00178   close_cam();
00179   open_cam(); // we only have this listener if camera should be active
00180 }
00181 
00182 
00183 void CameraDriverV4L2::close_cam()
00184 {
00185   if(camfd >= 0) {
00186     if (v_mem.size() > 0) {
00187       // unmap all buffers up to this point
00188       for (unsigned int i = 0; i < v_mem.size(); i++) {
00189         munmap( v_mem[i].start, v_mem[i].length );
00190       }
00191       v_mem.resize(0);
00192     }
00193 
00194     if (streaming)
00195       video_disable();
00196 
00197     ::close(camfd);
00198     camfd = -1;
00199   }
00200 }
00201 
00202 void CameraDriverV4L2::open_cam()
00203 {
00204   int ret;
00205 
00206   close_cam();
00207   if (path.size() == 0)
00208     return;
00209   
00210   // open the camera
00211   if ((camfd = ::open(path.c_str(), O_RDWR, 0)) == -1) {
00212     perror ("ERROR opening V4L interface \n");
00213     return;
00214   }
00215 
00216   // check capabilities
00217   memset( &v_cap, 0, sizeof (struct v4l2_capability) );
00218   ret = ioctl( camfd, VIDIOC_QUERYCAP, &v_cap);
00219   if (ret < 0) {
00220     perror("Unable to query capabilities");
00221     close_cam();
00222     return;
00223   }
00224 
00225   if ((v_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
00226     cout << "Error opening device " << path << ": video capture not supported.\n";
00227     close_cam();
00228     return;
00229   }
00230 
00231   if (!(v_cap.capabilities & V4L2_CAP_STREAMING)) {
00232     cout << path << " does not support streaming i/o\n";
00233     close_cam();
00234     return;
00235   }
00236 
00237   // setup the format
00238   if (select_format()) {
00239     cout << "Format selection failed.\n";
00240     close_cam();
00241     return;
00242   }
00243 
00244   // setup the buffers for capturing
00245   struct v4l2_requestbuffers v_rb;
00246   memset( &v_rb, 0, sizeof (struct v4l2_requestbuffers) );
00247   v_rb.count = NUM_BUFFERS;
00248   v_rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00249   v_rb.memory = V4L2_MEMORY_MMAP;
00250   
00251   ret = ioctl( camfd, VIDIOC_REQBUFS, &v_rb );
00252   if (ret < 0) {
00253     perror("Unable to allocate buffers");
00254     close_cam();
00255     return;
00256   }
00257   
00258   // how many buffers did we actually get
00259   if(v_rb.count!=NUM_BUFFERS)
00260     cout << "Allocated " << v_rb.count << " buffers for capturing.\n";
00261   if (v_rb.count < MIN_BUFFERS) {
00262     cout << "Not enough buffers allocated for capturing.\n";
00263     close_cam();
00264     return;
00265   }
00266   
00267   // we need to mmap memory for each buffer
00268   v_mem.resize( v_rb.count );
00269 
00270   for (unsigned int i = 0; i < v_rb.count; i++) {
00271     memset( &v_buf, 0, sizeof (struct v4l2_buffer) );
00272     v_buf.index = i;
00273     v_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00274     v_buf.memory = V4L2_MEMORY_MMAP;
00275     ret = ioctl( camfd, VIDIOC_QUERYBUF, &v_buf );
00276     if (ret < 0) {
00277       perror("Unable to query buffer");
00278       goto cleanup;
00279     }
00280     v_mem[i].length = v_buf.length;
00281     v_mem[i].start = mmap (NULL, v_buf.length,
00282                            PROT_READ | PROT_WRITE, MAP_SHARED,
00283                            camfd, v_buf.m.offset);
00284     if (v_mem[i].start == MAP_FAILED) {
00285       perror("Unable to map buffer");
00286       goto cleanup;
00287     }
00288 
00289     continue;
00290 
00291   cleanup:
00292     // unmap all buffers up to this point
00293     for (unsigned int j = 0; j < i; j++) {
00294       munmap( v_mem[j].start, v_mem[j].length );
00295     }
00296     v_mem.resize(0);
00297 
00298     // close up everything else
00299     close_cam();
00300     return;
00301   }
00302   
00303   for (int i = 0; i < NUM_BUFFERS; ++i) {
00304     memset (&v_buf, 0, sizeof (struct v4l2_buffer));
00305     v_buf.index = i;
00306     v_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00307     v_buf.memory = V4L2_MEMORY_MMAP;
00308     ret = ioctl (camfd, VIDIOC_QBUF, &v_buf);
00309     if (ret < 0) {
00310       perror("Unable to queue buffer");
00311       close_cam();
00312       return;
00313     }
00314   }
00315 
00316   // query the options for this camera (brightness, etc.)
00317   query_options(false);
00318 
00319   // set options
00320   for(plist::DictionaryOf< plist::Primitive<int> >::const_iterator it=userOptions.begin(); it!=userOptions.end(); ++it) {
00321     setControl(it->first,*it->second,false);
00322   }
00323 
00324   return;
00325 }
00326 
00327 bool CameraDriverV4L2::setControl(const std::string& name, int value, bool verbose/*=false*/) {
00328   map<std::string, struct v4l2_queryctrl>::const_iterator opt = options.find(name);
00329   if(opt==options.end()) {
00330     cerr << instanceName << " does not recognize setting " << name << std::endl;
00331     return false;
00332   }
00333     
00334   MarkScope l(lock);
00335 
00336   if(verbose)
00337     cout << "Setting \"" << (const char *)(opt->second.name) << "\" to " << value << "." << endl;
00338     
00339   struct v4l2_control control;
00340   control.id = opt->second.id;
00341   control.value = value;
00342   int error = ioctl(camfd, VIDIOC_S_CTRL, &control);
00343   if (error!=0)
00344     cerr << "Unable to set control \"" << (const char *)(opt->second.name) << "\"." << endl;
00345 
00346   return (error==0);
00347 }
00348 
00349 int CameraDriverV4L2::video_enable()
00350 {
00351   int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00352   int ret;
00353   
00354   ret = ioctl (camfd, VIDIOC_STREAMON, &type);
00355   if (ret < 0) {
00356     perror("Unable to %s capture: %d.");
00357     return ret;
00358   }
00359 
00360   streaming = true;
00361   
00362   return 0;
00363 }
00364 
00365 int CameraDriverV4L2::video_disable()
00366 {
00367   int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00368   int ret;
00369   
00370   ret = ioctl( camfd, VIDIOC_STREAMOFF, &type);
00371   if (ret < 0) {
00372     perror("Unable to stop capture:");
00373     return ret;
00374   }
00375   
00376   streaming = false;
00377 
00378   return 0;
00379 }
00380 
00381 string CameraDriverV4L2::v4l2_fourcc_inv(__u32 f)
00382 {
00383   char tmp[5];
00384   tmp[4] = 0;
00385   *((int *)tmp) = f;
00386 
00387   return string(tmp);
00388 }
00389 
00390 int CameraDriverV4L2::add_control(struct v4l2_queryctrl & queryctrl, bool v)
00391 {
00392   struct v4l2_querymenu querymenu;
00393   struct v4l2_control   control_s;
00394 
00395   control_s.id=queryctrl.id;
00396   ioctl(camfd, VIDIOC_G_CTRL, &control_s);
00397   
00398   stringstream ss;
00399   ss << "Type: " << queryctrl.type << ", values: [" << queryctrl.minimum << " - " << queryctrl.maximum << "], stepsize "
00400      << queryctrl.step << ", default " << queryctrl.default_value << ".";
00401   
00402   
00403   // add control to plist dictionary
00404   options[(char*)queryctrl.name] = queryctrl;
00405   
00406   if (v) {
00407     cout << "   " << (char*)(queryctrl.name) << ":     " << ss.str() << endl;
00408 
00409     if (queryctrl.type == V4L2_CTRL_TYPE_MENU) {
00410       printf ("    Menu items: ");
00411       memset (&querymenu, 0, sizeof (querymenu));
00412       querymenu.id = queryctrl.id;
00413       for (querymenu.index = queryctrl.minimum;
00414            (decltype(queryctrl.maximum))querymenu.index <= queryctrl.maximum;
00415            querymenu.index++) {
00416         if (0 == ioctl (camfd, VIDIOC_QUERYMENU, &querymenu)) {
00417           printf ("\n    index:%d name:%s", querymenu.index, querymenu.name);
00418         } else {
00419           printf ("error getting control menu");
00420           break;
00421         }
00422       }
00423       printf("\n");
00424     }
00425   }
00426 
00427   return 0;
00428 }
00429 
00430 int CameraDriverV4L2::query_options(bool v)
00431 {
00432   if (v)
00433     cout << "CAMERA DRIVER: Querying Camera Options" << endl;
00434 
00435   if (camfd < 0) {
00436     if (v)
00437       cout << "CAMERA DRIVER: No camera connected." << endl;
00438     return -1;
00439   }
00440 
00441   // remove old options from the plist dictionary
00442   options.clear();
00443   
00444   if (v)
00445     cout << endl << "CAMERA DRIVER: Available Frame Formats:" << endl;
00446 
00447   // enumerate frame formats and sizes
00448   int ret;
00449   int f = 0;
00450   struct v4l2_fmtdesc v_fmtdesc;
00451   while (true) {
00452     memset( &v_fmtdesc, 0, sizeof(struct v4l2_fmtdesc) );
00453     v_fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00454     v_fmtdesc.index = f;
00455   
00456     ret = ioctl( camfd, VIDIOC_ENUM_FMT, &v_fmtdesc );
00457     if (ret)
00458       break;
00459   
00460     if (v) {
00461       cout << "  " << v_fmtdesc.description << ":" << endl;
00462       cout << "    " << "Frame size enumeration disabled." << endl;
00463     }
00464 
00465     /*
00466       struct v4l2_frmsizeenum v_frmsize;
00467       int s = 0;
00468       while (true) {
00469       memset( &v_frmsize, 0, sizeof(struct v4l2_frmsizeenum) );
00470       v_frmsize.pixel_format = v_fmtdesc.pixelformat;
00471       v_frmsize.index = s;
00472     
00473       ret = ioctl( camfd, VIDIOC_ENUM_FRAMESIZES, &v_frmsize );
00474       if (ret)
00475       break;
00476     
00477       if (v_frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE)
00478       cout << "  " << v_frmsize.discrete.width << "x" << v_frmsize.discrete.height << "\n";
00479       else
00480       cout << "*****\n";
00481     
00482       s++;
00483       }*/
00484     f++;
00485   }
00486 
00487   //enumerate controls
00488   struct v4l2_queryctrl queryctrl;
00489   struct v4l2_input*    getinput;
00490   
00491   //Name of the device
00492   getinput=(struct v4l2_input *) calloc(1, sizeof(struct v4l2_input));
00493   memset(getinput, 0, sizeof(struct v4l2_input));
00494   getinput->index=0;
00495   ioctl(camfd, VIDIOC_ENUMINPUT, getinput);
00496   if (v) {
00497     cout << endl << "CAMERA DRIVER: Available controls (Type 1=Integer 2=Boolean 3=Menu 4=Button):" << endl;
00498   }
00499 
00500   // advanced enumeration code from libwebcam, written by quickcamteam:
00501   // http://www.quickcamteam.net/software/libwebcam
00502   queryctrl.id = 0 | V4L2_CTRL_FLAG_NEXT_CTRL;
00503   if (ioctl(camfd, VIDIOC_QUERYCTRL, &queryctrl) == 0) {
00504     if (v) {
00505       cout << "CAMERA DRIVER: Using advanced method of enumerating controls." << endl;
00506     }
00507     // The driver supports the V4L2_CTRL_FLAG_NEXT_CTRL flag, so go ahead with
00508     // the advanced enumeration way.
00509 
00510     int r;
00511     queryctrl.id = 0;
00512     int current_ctrl = queryctrl.id;
00513     queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
00514     // Loop as long as ioctl does not return EINVAL
00515     while ((r = ioctl(camfd, VIDIOC_QUERYCTRL, &queryctrl)), r ? errno != EINVAL : 1) {
00516 
00517       // Prevent infinite loop for buggy NEXT_CTRL implementations
00518       if(r && (int)queryctrl.id <= current_ctrl) {
00519         // If there was an error but the driver failed to provide us with the ID
00520         // of the next control, we have to manually increase the control ID,
00521         // otherwise we risk getting stuck querying the erroneous control.
00522         current_ctrl++;
00523         goto next_control;
00524       }
00525       current_ctrl = queryctrl.id;
00526 
00527       // Skip failed and disabled controls
00528       if(r || queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
00529         goto next_control;
00530 
00531       add_control(queryctrl, v);
00532 
00533     next_control:
00534       queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
00535     }
00536   } else {
00537     if (v) {
00538       cout << "CAMERA DRIVER: Using non-advanced method of enumerating controls." << endl;
00539     }
00540     //predefined controls
00541     memset (&queryctrl, 0, sizeof (queryctrl));
00542     for (int ctrl_id = V4L2_CID_BASE; ctrl_id < V4L2_CID_LASTP1; ctrl_id++) {
00543       queryctrl.id = ctrl_id;
00544       if (0 == ioctl (camfd, VIDIOC_QUERYCTRL, &queryctrl)) {
00545         if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
00546           continue;
00547         
00548         add_control(queryctrl, v);
00549         
00550       } else {
00551         if (errno == EINVAL)
00552           continue;
00553         perror ("error getting base controls");
00554       }
00555     }
00556     
00557     //driver specific controls
00558     for (queryctrl.id = V4L2_CID_PRIVATE_BASE;;
00559          queryctrl.id++) {
00560       if (0 == ioctl (camfd, VIDIOC_QUERYCTRL, &queryctrl)) {
00561         if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
00562           continue;
00563         
00564         add_control(queryctrl, v);
00565       } else {
00566         if (errno == EINVAL)
00567           break;
00568         perror ("error getting private base controls");
00569       }
00570     }
00571   }
00572   
00573   return 0;
00574 }
00575 
00576 int CameraDriverV4L2::select_format()
00577 {
00578   int ret;
00579 
00580   memset(&v_fmt, 0, sizeof (struct v4l2_format));
00581   v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00582   v_fmt.fmt.pix.field = V4L2_FIELD_ANY;
00583 
00584   // get the current format
00585   ret = ioctl(camfd, VIDIOC_G_FMT, &v_fmt);
00586   if (ret) {
00587     perror("Unable to get image format");
00588     return ret;
00589   }
00590 
00591   // set the mode:
00592   unsigned int w = 0, h = 0;
00593   char c;
00594   stringstream ss(resolution);
00595   ss >> w >> c >> h;
00596 
00597   v_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
00598   v_fmt.fmt.pix.width = w*2;
00599   v_fmt.fmt.pix.height = h*2;
00600   
00601   cout << "Trying " << v_fmt.fmt.pix.width << "x" << v_fmt.fmt.pix.height << "\n";
00602 
00603   // unable to set to double size, try for upsampled resolution
00604   if (ioctl(camfd, VIDIOC_S_FMT, &v_fmt) ||
00605       (v_fmt.fmt.pix.width != w*2) ||
00606       (v_fmt.fmt.pix.height != h*2)) {
00607 
00608     v_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
00609     v_fmt.fmt.pix.width = w;
00610     v_fmt.fmt.pix.height = h;
00611 
00612     cout << "Trying " << v_fmt.fmt.pix.width << "x" << v_fmt.fmt.pix.height << "\n";
00613 
00614     ret = ioctl(camfd, VIDIOC_S_FMT, &v_fmt);
00615     if (ret < 0) {
00616       perror("Unable to set format.");
00617       return ret;
00618     }
00619 
00620     if ((v_fmt.fmt.pix.width != w) ||
00621         (v_fmt.fmt.pix.height != h)) {
00622       cout << "Format asked unavailable.\n";
00623     }
00624 
00625     downsample = false;
00626     cout << "Image will be upsampled to " << v_fmt.fmt.pix.width << "x"
00627          << v_fmt.fmt.pix.height << ".\n";
00628   }
00629   else {
00630     downsample = true;
00631     cout << "Image will be downsampled to " << v_fmt.fmt.pix.width/2 << "x"
00632          << v_fmt.fmt.pix.height/2 << ".\n";
00633   }
00634 
00635   return 0;
00636 }
00637 
00638 void CameraDriverV4L2::downsample_yuyv()
00639 {
00640   unsigned int layer = 0, components = 3;
00641   unsigned int width = v_fmt.fmt.pix.width / 2;
00642   unsigned int height = v_fmt.fmt.pix.height / 2;
00643   
00644   ssize_t reqSize = sizeof(ImageHeader) + width * height * components;
00645   RCRegion* region = getUnusedRegion(reqSize,0);
00646   unsigned char * buf = reinterpret_cast<unsigned char*>(region->Base());
00647   new (buf) ImageHeader(0, layer, width, height, components, frameCount, timestamp, nextName());
00648   
00649   unsigned char * src = &captureBuf[0];
00650   const unsigned int srcStride=v_fmt.fmt.pix.width * 2;
00651   unsigned char * dst = buf + sizeof(ImageHeader);
00652   unsigned char * const dstEnd = dst + width*height*components;
00653 
00654   // convert!
00655   while (dst != dstEnd) {
00656     unsigned char * const rowEnd = dst + width * components;
00657     while (dst != rowEnd) {
00658       int y;
00659       int u, v;
00660     
00661       y=*src;
00662       y+=*(src+srcStride);
00663       ++src;
00664     
00665       u=*src;
00666       u+=*(src+srcStride);
00667       ++src;
00668     
00669       y+=*src;
00670       y+=*(src+srcStride);
00671       ++src;
00672     
00673       v=*src;
00674       v+=*(src+srcStride);
00675       ++src;
00676             
00677       *dst++ = y/4;
00678       *dst++ = u/2;
00679       *dst++ = v/2;
00680     }
00681     src+=srcStride;
00682   }
00683   ASSERTRET(dst-buf==reqSize,"CameraDriverV4L2 bad downsample_yuyv " << reqSize << " vs " << (dst-buf));
00684   setImage(region);
00685 }
00686 
00687 void CameraDriverV4L2::upsample_yuyv()
00688 {
00689   unsigned int layer = 0, components = 3;
00690   unsigned int width = v_fmt.fmt.pix.width;
00691   unsigned int height = v_fmt.fmt.pix.height;
00692   
00693   ssize_t reqSize = sizeof(ImageHeader) + width * height * components;
00694   RCRegion* region = getUnusedRegion(reqSize,0);
00695   unsigned char * buf = reinterpret_cast<unsigned char*>(region->Base());
00696   new (buf) ImageHeader(0, layer, width, height, components, frameCount, timestamp, nextName());
00697   
00698   // setup pointers
00699   unsigned char * src = &captureBuf[0];
00700   unsigned char * dst = buf + sizeof(ImageHeader);
00701   unsigned char * const dstEnd = dst + width*height*components;
00702 
00703   // convert!
00704   while (dst != dstEnd) {
00705     unsigned char * const rowEnd = dst + width * components;
00706     while (dst != rowEnd) {
00707       int y1, y2;
00708       int u, v;
00709     
00710       y1=*src;
00711       ++src;
00712     
00713       u=*src;
00714       ++src;
00715     
00716       y2=*src;
00717       ++src;
00718     
00719       v=*src;
00720       ++src;
00721             
00722       *dst++ = y1;
00723       *dst++ = u;
00724       *dst++ = v;
00725       *dst++ = y2;
00726       *dst++ = u;
00727       *dst++ = v;
00728     }
00729   }
00730   ASSERTRET(dst-buf==reqSize,"CameraDriverV4L2 bad upsample_yuyv " << reqSize << " vs " << (dst-buf));
00731   setImage(region);
00732 }
00733 
00734 /*! @file
00735  * @brief 
00736  * @author Alex Grubb (agrubb1) (V4L2 code)
00737  * @author Ethan Tira-Thompson (ejt) (Framework)
00738  */
00739 
00740 #endif

Tekkotsu Hardware Abstraction Layer 5.1CVS
Generated Mon May 9 05:01:38 2016 by Doxygen 1.6.3