Home | History | Annotate | Download | only in src
      1 /*M///////////////////////////////////////////////////////////////////////////////////////
      2 //
      3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
      4 //
      5 //  By downloading, copying, installing or using the software you agree to this license.
      6 //  If you do not agree to this license, do not download, install,
      7 //  copy or use the software.
      8 //
      9 //
     10 //                        Intel License Agreement
     11 //                For Open Source Computer Vision Library
     12 //
     13 // Copyright (C) 2008, Xavier Delacour, all rights reserved.
     14 // Third party copyrights are property of their respective owners.
     15 //
     16 // Redistribution and use in source and binary forms, with or without modification,
     17 // are permitted provided that the following conditions are met:
     18 //
     19 //   * Redistribution's of source code must retain the above copyright notice,
     20 //     this list of conditions and the following disclaimer.
     21 //
     22 //   * Redistribution's in binary form must reproduce the above copyright notice,
     23 //     this list of conditions and the following disclaimer in the documentation
     24 //     and/or other materials provided with the distribution.
     25 //
     26 //   * The name of Intel Corporation may not be used to endorse or promote products
     27 //     derived from this software without specific prior written permission.
     28 //
     29 // This software is provided by the copyright holders and contributors "as is" and
     30 // any express or implied warranties, including, but not limited to, the implied
     31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
     32 // In no event shall the Intel Corporation or contributors be liable for any direct,
     33 // indirect, incidental, special, exemplary, or consequential damages
     34 // (including, but not limited to, procurement of substitute goods or services;
     35 // loss of use, data, or profits; or business interruption) however caused
     36 // and on any theory of liability, whether in contract, strict liability,
     37 // or tort (including negligence or otherwise) arising in any way out of
     38 // the use of this software, even if advised of the possibility of such damage.
     39 //
     40 //M*/
     41 
     42 // 2008-04-27 Xavier Delacour <xavier.delacour (at) gmail.com>
     43 
     44 #include "precomp.hpp"
     45 #include <unistd.h>
     46 #include <unicap.h>
     47 extern "C" {
     48 #include <ucil.h>
     49 }
     50 
     51 #ifdef NDEBUG
     52 #define CV_WARN(message)
     53 #else
     54 #define CV_WARN(message) fprintf(stderr, "warning: %s (%s:%d)\n", message, __FILE__, __LINE__)
     55 #endif
     56 
     57 struct CvCapture_Unicap : public CvCapture
     58 {
     59   CvCapture_Unicap() { init(); }
     60   virtual ~CvCapture_Unicap() { close(); }
     61 
     62   virtual bool open( int index );
     63   virtual void close();
     64 
     65   virtual double getProperty(int) const;
     66   virtual bool setProperty(int, double);
     67   virtual bool grabFrame();
     68   virtual IplImage* retrieveFrame(int);
     69   virtual int getCaptureDomain() { return CV_CAP_UNICAP; } // Return the type of the capture object: CV_CAP_VFW, etc...
     70 
     71   bool shutdownDevice();
     72   bool initDevice();
     73 
     74   void init()
     75   {
     76     device_initialized = false;
     77     desired_format = 0;
     78     desired_size = cvSize(0,0);
     79     convert_rgb = false;
     80 
     81     handle = 0;
     82     memset( &device, 0, sizeof(device) );
     83     memset( &format_spec, 0, sizeof(format_spec) );
     84     memset( &format, 0, sizeof(format) );
     85     memset( &raw_buffer, 0, sizeof(raw_buffer) );
     86     memset( &buffer, 0, sizeof(buffer) );
     87 
     88     raw_frame = frame = 0;
     89   }
     90 
     91   bool device_initialized;
     92 
     93   int desired_device;
     94   int desired_format;
     95   CvSize desired_size;
     96   bool convert_rgb;
     97 
     98   unicap_handle_t handle;
     99   unicap_device_t device;
    100   unicap_format_t format_spec;
    101   unicap_format_t format;
    102   unicap_data_buffer_t raw_buffer;
    103   unicap_data_buffer_t buffer;
    104 
    105   IplImage *raw_frame;
    106   IplImage *frame;
    107 };
    108 
    109 bool CvCapture_Unicap::shutdownDevice() {
    110   bool result = false;
    111   CV_FUNCNAME("CvCapture_Unicap::shutdownDevice");
    112   __BEGIN__;
    113 
    114   if (!SUCCESS(unicap_stop_capture(handle)))
    115     CV_ERROR(CV_StsError, "unicap: failed to stop capture on device\n");
    116 
    117   if (!SUCCESS(unicap_close(handle)))
    118     CV_ERROR(CV_StsError, "unicap: failed to close the device\n");
    119 
    120   cvReleaseImage(&raw_frame);
    121   cvReleaseImage(&frame);
    122 
    123   device_initialized = false;
    124 
    125   result = true;
    126   __END__;
    127   return result;
    128 }
    129 
    130 bool CvCapture_Unicap::initDevice() {
    131   bool result = false;
    132   CV_FUNCNAME("CvCapture_Unicap::initDevice");
    133   __BEGIN__;
    134 
    135   if (device_initialized && !shutdownDevice())
    136     return false;
    137 
    138   if(!SUCCESS(unicap_enumerate_devices(NULL, &device, desired_device)))
    139     CV_ERROR(CV_StsError, "unicap: failed to get info for device\n");
    140 
    141   if(!SUCCESS(unicap_open( &handle, &device)))
    142     CV_ERROR(CV_StsError, "unicap: failed to open device\n");
    143 
    144   unicap_void_format(&format_spec);
    145 
    146   if (!SUCCESS(unicap_enumerate_formats(handle, &format_spec, &format, desired_format))) {
    147     shutdownDevice();
    148     CV_ERROR(CV_StsError, "unicap: failed to get video format\n");
    149   }
    150 
    151   int i;
    152   if (format.sizes)
    153   {
    154       for (i = format.size_count - 1; i > 0; i--)
    155         if (format.sizes[i].width == desired_size.width &&
    156         format.sizes[i].height == desired_size.height)
    157           break;
    158       format.size.width = format.sizes[i].width;
    159       format.size.height = format.sizes[i].height;
    160   }
    161 
    162   if (!SUCCESS(unicap_set_format(handle, &format))) {
    163     shutdownDevice();
    164     CV_ERROR(CV_StsError, "unicap: failed to set video format\n");
    165   }
    166 
    167   memset(&raw_buffer, 0x0, sizeof(unicap_data_buffer_t));
    168   raw_frame = cvCreateImage(cvSize(format.size.width,
    169                     format.size.height),
    170                   8, format.bpp / 8);
    171   memcpy(&raw_buffer.format, &format, sizeof(raw_buffer.format));
    172   raw_buffer.data = (unsigned char*)raw_frame->imageData;
    173   raw_buffer.buffer_size = format.size.width *
    174     format.size.height * format.bpp / 8;
    175 
    176   memset(&buffer, 0x0, sizeof(unicap_data_buffer_t));
    177   memcpy(&buffer.format, &format, sizeof(buffer.format));
    178 
    179   buffer.format.fourcc = UCIL_FOURCC('B','G','R','3');
    180   buffer.format.bpp = 24;
    181   // * todo support greyscale output
    182   //    buffer.format.fourcc = UCIL_FOURCC('G','R','E','Y');
    183   //    buffer.format.bpp = 8;
    184 
    185   frame = cvCreateImage(cvSize(buffer.format.size.width,
    186                     buffer.format.size.height),
    187                   8, buffer.format.bpp / 8);
    188   buffer.data = (unsigned char*)frame->imageData;
    189   buffer.buffer_size = buffer.format.size.width *
    190     buffer.format.size.height * buffer.format.bpp / 8;
    191 
    192   if(!SUCCESS(unicap_start_capture(handle))) {
    193     shutdownDevice();
    194     CV_ERROR(CV_StsError, "unicap: failed to start capture on device\n");
    195   }
    196 
    197   device_initialized = true;
    198   result = true;
    199   __END__;
    200   return result;
    201 }
    202 
    203 void CvCapture_Unicap::close() {
    204   if(device_initialized)
    205     shutdownDevice();
    206 }
    207 
    208 bool CvCapture_Unicap::grabFrame() {
    209   bool result = false;
    210 
    211   CV_FUNCNAME("CvCapture_Unicap::grabFrame");
    212   __BEGIN__;
    213 
    214   unicap_data_buffer_t *returned_buffer;
    215 
    216   int retry_count = 100;
    217 
    218   while (retry_count--) {
    219     if(!SUCCESS(unicap_queue_buffer(handle, &raw_buffer)))
    220       CV_ERROR(CV_StsError, "unicap: failed to queue a buffer on device\n");
    221 
    222     if(SUCCESS(unicap_wait_buffer(handle, &returned_buffer)))
    223     {
    224       result = true;
    225       EXIT;
    226     }
    227 
    228     CV_WARN("unicap: failed to wait for buffer on device\n");
    229     usleep(100 * 1000);
    230   }
    231 
    232   __END__;
    233   return result;
    234 }
    235 
    236 IplImage * CvCapture_Unicap::retrieveFrame(int) {
    237   if (convert_rgb) {
    238     ucil_convert_buffer(&buffer, &raw_buffer);
    239     return frame;
    240   }
    241   return raw_frame;
    242 }
    243 
    244 double CvCapture_Unicap::getProperty(int id) const
    245 {
    246   switch (id) {
    247   case CV_CAP_PROP_POS_MSEC: break;
    248   case CV_CAP_PROP_POS_FRAMES: break;
    249   case CV_CAP_PROP_POS_AVI_RATIO: break;
    250   case CV_CAP_PROP_FRAME_WIDTH:
    251     return desired_size.width;
    252   case CV_CAP_PROP_FRAME_HEIGHT:
    253     return desired_size.height;
    254   case CV_CAP_PROP_FPS: break;
    255   case CV_CAP_PROP_FOURCC: break;
    256   case CV_CAP_PROP_FRAME_COUNT: break;
    257   case CV_CAP_PROP_FORMAT:
    258     return desired_format;
    259   case CV_CAP_PROP_MODE: break;
    260   case CV_CAP_PROP_BRIGHTNESS: break;
    261   case CV_CAP_PROP_CONTRAST: break;
    262   case CV_CAP_PROP_SATURATION: break;
    263   case CV_CAP_PROP_HUE: break;
    264   case CV_CAP_PROP_GAIN: break;
    265   case CV_CAP_PROP_CONVERT_RGB:
    266     return convert_rgb;
    267   }
    268 
    269   return 0;
    270 }
    271 
    272 bool CvCapture_Unicap::setProperty(int id, double value) {
    273   bool reinit = false;
    274 
    275   switch (id) {
    276   case CV_CAP_PROP_POS_MSEC: break;
    277   case CV_CAP_PROP_POS_FRAMES: break;
    278   case CV_CAP_PROP_POS_AVI_RATIO: break;
    279   case CV_CAP_PROP_FRAME_WIDTH:
    280     desired_size.width = (int)value;
    281     reinit = true;
    282     break;
    283   case CV_CAP_PROP_FRAME_HEIGHT:
    284     desired_size.height = (int)value;
    285     reinit = true;
    286     break;
    287   case CV_CAP_PROP_FPS: break;
    288   case CV_CAP_PROP_FOURCC: break;
    289   case CV_CAP_PROP_FRAME_COUNT: break;
    290   case CV_CAP_PROP_FORMAT:
    291     desired_format = id;
    292     reinit = true;
    293     break;
    294   case CV_CAP_PROP_MODE: break;
    295   case CV_CAP_PROP_BRIGHTNESS: break;
    296   case CV_CAP_PROP_CONTRAST: break;
    297   case CV_CAP_PROP_SATURATION: break;
    298   case CV_CAP_PROP_HUE: break;
    299   case CV_CAP_PROP_GAIN: break;
    300   case CV_CAP_PROP_CONVERT_RGB:
    301     convert_rgb = value != 0;
    302     break;
    303   }
    304 
    305   if (reinit && !initDevice())
    306     return false;
    307 
    308   return true;
    309 }
    310 
    311 bool CvCapture_Unicap::open(int index)
    312 {
    313   close();
    314   device_initialized = false;
    315 
    316   desired_device = index < 0 ? 0 : index;
    317   desired_format = 0;
    318   desired_size = cvSize(320, 240);
    319   convert_rgb = true;
    320 
    321   return initDevice();
    322 }
    323 
    324 
    325 CvCapture * cvCreateCameraCapture_Unicap(const int index)
    326 {
    327   CvCapture_Unicap *cap = new CvCapture_Unicap;
    328   if( cap->open(index) )
    329     return cap;
    330   delete cap;
    331   return 0;
    332 }
    333