• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kstars

v4l1_base.cpp

Go to the documentation of this file.
00001 /*
00002     Copyright (C) 2005 by Jasem Mutlaq
00003 
00004     Some code based on qastrocam
00005 
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Lesser General Public
00008     License as published by the Free Software Foundation; either
00009     version 2.1 of the License, or (at your option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     Lesser General Public License for more details.
00015 
00016     You should have received a copy of the GNU Lesser General Public
00017     License along with this library; if not, write to the Free Software
00018     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00019 
00020 */
00021 
00022 #include <iostream>
00023 
00024 #include <sys/ioctl.h>
00025 #include <sys/types.h>
00026 #include <sys/stat.h>
00027 #include <fcntl.h>
00028 #include <unistd.h>
00029 #include <stdio.h>
00030 #include <errno.h>
00031 #include <sys/mman.h>
00032 #include <string.h>
00033 
00034 #include "ccvt.h"
00035 #include "v4l1_base.h"
00036 #include "../eventloop.h"
00037 #include "../indidevapi.h"
00038 
00039 #define ERRMSGSIZ   1024
00040 
00041 using namespace std;
00042 
00043 V4L1_Base::V4L1_Base()
00044 {
00045    frameRate=10;
00046    fd=-1;
00047    //usingTimer = false;
00048    
00049    //frameUpdate = true;
00050    //selectCallBackID = -1;
00051    //timerCallBackID  = -1;
00052 
00053    YBuf       = NULL;
00054    UBuf       = NULL;
00055    VBuf       = NULL;
00056    colorBuffer= NULL;
00057    buffer_start=NULL;
00058 
00059 }
00060 
00061 V4L1_Base::~V4L1_Base()
00062 {
00063 
00064   delete (YBuf);
00065   delete (UBuf);
00066   delete (VBuf);
00067   delete (colorBuffer);
00068 
00069 }
00070 
00071 int V4L1_Base::connectCam(const char * devpath, char *errmsg)
00072 {
00073    options= (haveBrightness|haveContrast|haveHue|haveColor|haveWhiteness);
00074 
00075    buffer_start=NULL;
00076    frameRate=10;
00077    fd=-1;
00078    //usingTimer = false;
00079    
00080    //frameUpdate = true;
00081    //selectCallBackID = -1;
00082    //timerCallBackID  = -1;
00083    
00084    cerr << "In connect Cam with device " << devpath << endl;
00085    if (-1 == (fd=open(devpath, O_RDONLY | O_NONBLOCK, 0)))
00086    {
00087       strncpy(errmsg, strerror(errno), ERRMSGSIZ);
00088       cerr << strerror(errno);
00089       return -1;
00090    }
00091    
00092    cerr << "Device opened" << endl;
00093    
00094    if (fd != -1) 
00095    {
00096       if (-1 == ioctl(fd,VIDIOCGCAP,&capability))
00097      {
00098          cerr << "Error: ioctl (VIDIOCGCAP)" << endl;
00099      strncpy(errmsg, "ioctl (VIDIOCGCAP)", ERRMSGSIZ);
00100      return -1;
00101       }
00102       if (-1 == ioctl (fd, VIDIOCGWIN, &window))
00103       {
00104          cerr << "Error ioctl (VIDIOCGWIN)" << endl;
00105      strncpy(errmsg, "ioctl (VIDIOCGWIN)", ERRMSGSIZ);
00106      return -1;
00107       }
00108       if (-1 == ioctl (fd, VIDIOCGPICT, &picture_format))
00109       {
00110          cerr << "Error: ioctl (VIDIOCGPICT)" << endl;
00111      strncpy(errmsg, "ioctl (VIDIOCGPICT)", ERRMSGSIZ);
00112      return -1;
00113       }
00114 
00115       init(0);
00116    }
00117 
00118    cerr << "initial size w:" << window.width << " -- h: " << window.height << endl;
00119 
00120    /*if (options & ioUseSelect)
00121    {
00122       selectCallBackID = addCallback(fd, V4L1_Base::staticUpdateFrame, this);
00123       cerr << "Using select to wait new frames." << endl;
00124    } else
00125    {
00126       usingTimer = true;
00127       timerCallBackID = addTimer(1000/frameRate, V4L1_Base::staticCallFrame, this);
00128       cerr << "Using timer to wait new frames.\n";
00129    }
00130     */
00131 
00132    mmapInit();
00133       //mmapCapture();
00134    
00135    cerr << "All successful, returning\n";
00136    return fd;
00137 }
00138 
00139 void V4L1_Base::disconnectCam()
00140 {
00141    
00142    
00143    delete YBuf;
00144    delete UBuf;
00145    delete VBuf;
00146    YBuf = UBuf = VBuf = NULL;
00147    
00148    if (selectCallBackID != -1)
00149      rmCallback(selectCallBackID);
00150      
00151    //if (usingTimer && timerCallBackID != -1)
00152      //rmTimer(timerCallBackID);
00153      
00154    if (munmap (buffer_start, mmap_buffer.size) < 0)
00155      fprintf(stderr, "munmap: %s\n", strerror(errno));
00156      
00157    if (close(fd) < 0)
00158      fprintf(stderr, "close(fd): %s\n", strerror(errno));
00159      
00160    fprintf(stderr, "Disconnect cam\n");
00161 }
00162 
00163 //void V4L1_Base::staticCallFrame(void *p)
00164 //{
00165 //  ((V4L1_Base *) p)->updateFrame(0, NULL);
00166 //}
00167 
00168 //void V4L1_Base::staticUpdateFrame(int /*d*/, void *p)
00169 //{
00170 //  ((V4L1_Base *) p)->updateFrame(0, NULL);
00171 //}
00172 
00173 void V4L1_Base::newFrame() 
00174 {
00175       switch (picture_format.palette) 
00176       {
00177        case VIDEO_PALETTE_GREY:
00178          memcpy(YBuf,mmapFrame(),window.width * window.height);
00179          break;
00180        case VIDEO_PALETTE_YUV420P:
00181          memcpy(YBuf,mmapFrame(), window.width * window.height);
00182          memcpy(UBuf,
00183                 mmapFrame()+ window.width * window.height,
00184                 (window.width/2) * (window.height/2));
00185          memcpy(VBuf,
00186                 mmapFrame()+ window.width * window.height+(window.width/2) * (window.height/2),
00187                 (window.width/2) * (window.height/2));
00188          break;
00189       case VIDEO_PALETTE_YUYV:
00190          ccvt_yuyv_420p(window.width,window.height,
00191                            mmapFrame(),
00192                            YBuf,
00193                            UBuf,
00194                            VBuf);
00195          break;
00196 
00197      case VIDEO_PALETTE_RGB24:
00198         RGB2YUV(window.width, window.height, mmapFrame(), YBuf, UBuf, VBuf, 0);
00199         break;
00200 
00201       default: 
00202          cerr << "invalid palette " <<picture_format.palette << endl;
00203          exit(1);
00204       }
00205    
00206    
00207     if (callback)
00208       (*callback)(uptr);
00209 
00210 }
00211 
00212 void V4L1_Base::updateFrame(int /*d*/, void * p)
00213 {
00214 
00215   ( (V4L1_Base *) (p))->newFrame();
00216 
00217 }
00218 
00219 int V4L1_Base::start_capturing(char * /*errmsg*/)
00220 {
00221    
00222    mmapCapture();
00223    mmapSync();
00224 
00225    selectCallBackID = IEAddCallback(fd, updateFrame, this);
00226    //newFrame();
00227    return 0;
00228 }
00229 
00230 int V4L1_Base::stop_capturing(char * /*errmsg*/)
00231 {
00232   
00233   IERmCallback(selectCallBackID);
00234   selectCallBackID = -1;
00235   return 0;
00236 }
00237  
00238 int V4L1_Base::getWidth()
00239 {
00240   return window.width;
00241 }
00242 
00243 int V4L1_Base::getHeight()
00244 {
00245  return window.height;
00246 }
00247 
00248 void V4L1_Base::setFPS(int fps)
00249 {
00250   frameRate = fps;
00251 }
00252 
00253 int V4L1_Base::getFPS()
00254 {
00255   return frameRate;
00256 }
00257 
00258 char * V4L1_Base::getDeviceName()
00259 {
00260   return capability.name;
00261 }
00262 
00263 void V4L1_Base::init(int preferedPalette)
00264  {
00265 
00266    if (preferedPalette)
00267    {
00268       picture_format.palette=preferedPalette;
00269       if (0 == ioctl(fd, VIDIOCSPICT, &picture_format))
00270         cerr <<  "found preferedPalette " << preferedPalette << endl;
00271       else
00272       {
00273          preferedPalette=0;
00274          cerr << "preferedPalette " << preferedPalette << " invalid, trying to find one." << endl;
00275       }
00276    }
00277 
00278    if (preferedPalette == 0)
00279    {
00280       do {
00281       /* trying VIDEO_PALETTE_YUV420P (Planar) */
00282       picture_format.palette=VIDEO_PALETTE_YUV420P;
00283       if (0 == ioctl(fd, VIDIOCSPICT, &picture_format)) {
00284          cerr << "found palette VIDEO_PALETTE_YUV420P" << endl;
00285      break;
00286       }
00287       cerr << "VIDEO_PALETTE_YUV420P not supported." << endl;
00288       /* trying VIDEO_PALETTE_YUV420 (interlaced) */
00289       picture_format.palette=VIDEO_PALETTE_YUV420;
00290       if ( 0== ioctl(fd, VIDIOCSPICT, &picture_format)) {
00291          cerr << "found palette VIDEO_PALETTE_YUV420" << endl;
00292      break;
00293       }
00294       cerr << "VIDEO_PALETTE_YUV420 not supported." << endl;
00295       /* trying VIDEO_PALETTE_RGB24 */
00296       picture_format.palette=VIDEO_PALETTE_RGB24;
00297       if ( 0== ioctl(fd, VIDIOCSPICT, &picture_format)) {
00298          cerr << "found palette VIDEO_PALETTE_RGB24" << endl;
00299       break;
00300       }
00301       cerr << "VIDEO_PALETTE_RGB24 not supported." << endl;
00302       /* trying VIDEO_PALETTE_GREY */
00303       picture_format.palette=VIDEO_PALETTE_GREY;
00304       if ( 0== ioctl(fd, VIDIOCSPICT, &picture_format)) {
00305          cerr << "found palette VIDEO_PALETTE_GREY" << endl;
00306       break;
00307       }
00308       cerr << "VIDEO_PALETTE_GREY not supported." << endl;
00309       cerr << "could not find a supported palette." << endl;
00310       exit(1);
00311       } while (false);
00312    }
00313 
00314    allocBuffers();
00315 
00316 }
00317 
00318 void V4L1_Base::allocBuffers()
00319 {
00320    delete YBuf;
00321    delete UBuf;
00322    delete VBuf;
00323    delete colorBuffer;
00324 
00325    YBuf= new unsigned char[window.width * window.height];
00326    UBuf= new unsigned char[window.width * window.height];
00327    VBuf= new unsigned char[window.width * window.height];
00328    colorBuffer = new unsigned char[window.width * window.height * 4];
00329 }
00330 
00331 void V4L1_Base::checkSize(int & x, int & y)
00332 {
00333    if (x >= capability.maxwidth && y >= capability.maxheight)
00334    {
00335       x=capability.maxwidth;
00336       y=capability.maxheight;
00337    }
00338    else if (x>=352 && y >=288) {
00339       x=352;y=288;
00340    } else if (x>=320 && y >= 240) {
00341       x=320;y=240;
00342    } else if (x>=176 && y >=144) {
00343       x=176;y=144;
00344    } else if (x>=160 && y >=120 ) {
00345       x=160;y=120;
00346    } else
00347    {
00348       x=capability.minwidth;
00349       y=capability.minheight;
00350    }
00351 }
00352 
00353 void V4L1_Base::getMaxMinSize(int & xmax, int & ymax, int & xmin, int & ymin)
00354 {
00355   xmax = capability.maxwidth;
00356   ymax = capability.maxheight;
00357   xmin = capability.minwidth;
00358   ymin = capability.minheight;
00359 }
00360 
00361 bool V4L1_Base::setSize(int x, int y)
00362 {
00363    int oldX, oldY;
00364    checkSize(x,y);
00365    
00366    oldX = window.width;
00367    oldY = window.height;
00368    
00369    window.width=x;
00370    window.height=y;
00371 
00372    cerr << "New size is x=" << window.width << " " << "y=" << window.height <<endl;
00373    
00374    if (ioctl (fd, VIDIOCSWIN, &window))
00375    {
00376        cerr << "ioctl(VIDIOCSWIN)" << endl;
00377        window.width=oldX;
00378        window.height=oldY;
00379        return false;
00380    }
00381    ioctl (fd, VIDIOCGWIN, &window);
00382 
00383    allocBuffers();
00384    
00385    return true;
00386 }
00387 
00388 void V4L1_Base::setContrast(int val)
00389 {
00390    picture_format.contrast=val;
00391    setPictureSettings();
00392 }
00393 
00394 int V4L1_Base::getContrast()
00395 {
00396    return picture_format.contrast;
00397 }
00398 
00399 void V4L1_Base::setBrightness(int val)
00400 {
00401    picture_format.brightness=val;
00402    setPictureSettings();
00403 }
00404 
00405 int V4L1_Base::getBrightness()
00406 {
00407    return picture_format.brightness;
00408 }
00409 
00410 void V4L1_Base::setColor(int val)
00411 {
00412    picture_format.colour=val;
00413    setPictureSettings();
00414 }
00415 
00416 int V4L1_Base::getColor()
00417 {
00418    return picture_format.colour;
00419 }
00420 
00421 void V4L1_Base::setHue(int val)
00422 {
00423    picture_format.hue=val;
00424    setPictureSettings();
00425 }
00426 
00427 int V4L1_Base::getHue()
00428 {
00429    return picture_format.hue;
00430 }
00431 
00432 void V4L1_Base::setWhiteness(int val)
00433 {
00434    picture_format.whiteness=val;
00435    setPictureSettings();
00436 }
00437 
00438 int V4L1_Base::getWhiteness() 
00439 {
00440    return picture_format.whiteness;
00441 }
00442 
00443 void V4L1_Base::setPictureSettings()
00444 {
00445    if (ioctl(fd, VIDIOCSPICT, &picture_format) ) {
00446       cerr << "setPictureSettings" << endl;
00447    }
00448    ioctl(fd, VIDIOCGPICT, &picture_format);
00449 }
00450 
00451 void V4L1_Base::getPictureSettings()
00452 {
00453    if (ioctl(fd, VIDIOCGPICT, &picture_format) )
00454    {
00455       cerr << "getPictureSettings" << endl;
00456    }
00457 }
00458 
00459 int V4L1_Base::mmapInit()
00460 {
00461    mmap_buffer.size = 0;
00462    mmap_buffer.frames = 0;
00463 
00464    mmap_sync_buffer=-1;
00465    mmap_capture_buffer=-1;
00466    buffer_start=NULL;
00467 
00468    if (ioctl(fd, VIDIOCGMBUF, &mmap_buffer)) {
00469       // mmap not supported
00470       return -1;
00471    }
00472 
00473    buffer_start = (unsigned char *) mmap (NULL, mmap_buffer.size, PROT_READ, MAP_SHARED, fd, 0);
00474 
00475    if (buffer_start == MAP_FAILED)
00476     {
00477       cerr << "mmap" << endl;
00478       mmap_buffer.size = 0;
00479       mmap_buffer.frames = 0;
00480       buffer_start=NULL;
00481       return -1;
00482    }
00483 
00484    return 0;
00485 }
00486 
00487 void V4L1_Base::mmapCapture() 
00488 {
00489    
00490    struct video_mmap vm;
00491    mmap_capture_buffer = (mmap_capture_buffer + 1) % mmap_buffer.frames;
00492 
00493    vm.frame = mmap_capture_buffer;
00494    vm.format = picture_format.palette;
00495    vm.width = window.width;
00496    vm.height = window.height;
00497 
00498    if (ioctl(fd, VIDIOCMCAPTURE, &vm) < 0)
00499         cerr << "Error V4L1_Base::mmapCapture" << endl;
00500 }
00501 
00502 void V4L1_Base::mmapSync()
00503 {
00504    mmap_sync_buffer= (mmap_sync_buffer + 1) % mmap_buffer.frames;
00505 
00506    if (ioctl(fd, VIDIOCSYNC, &mmap_sync_buffer) < 0)
00507       cerr << "Error V4L1_Base::mmapSync()" << endl;
00508 }
00509 
00510 unsigned char * V4L1_Base::mmapFrame()
00511 {
00512    return (buffer_start + mmap_buffer.offsets[mmap_sync_buffer]);
00513 }
00514 
00515 unsigned char * V4L1_Base::getY()
00516 {
00517   return YBuf;
00518 }
00519 
00520 unsigned char * V4L1_Base::getU()
00521 {
00522  return UBuf;
00523 }
00524 
00525 unsigned char * V4L1_Base::getV()
00526 {
00527  return VBuf;
00528 }
00529 
00530 unsigned char * V4L1_Base::getColorBuffer()
00531 {
00532   //cerr << "in get color buffer " << endl;
00533   
00534   switch (picture_format.palette) 
00535   {
00536       case VIDEO_PALETTE_YUV420P:
00537         ccvt_420p_bgr32(window.width, window.height,
00538                       mmapFrame(), (void*)colorBuffer);
00539       break;
00540 
00541     case VIDEO_PALETTE_YUYV:
00542          ccvt_yuyv_bgr32(window.width, window.height,
00543                       mmapFrame(), (void*)colorBuffer);
00544          break;
00545      
00546     case VIDEO_PALETTE_RGB24:
00547          ccvt_rgb24_bgr32(window.width, window.height,
00548                       mmapFrame(), (void*)colorBuffer);
00549          break;
00550      
00551    default:
00552     break;
00553   }
00554   
00555 
00556   return colorBuffer;
00557 
00558 }
00559 
00560 void V4L1_Base::registerCallback(WPF *fp, void *ud)
00561 {
00562   callback = fp;
00563   uptr = ud;
00564 }

kstars

Skip menu "kstars"
  • Main Page
  • Modules
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • keduca
  • kstars
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal