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@gmail.com> 43 44#include "precomp.hpp" 45#include <unistd.h> 46#include <unicap.h> 47extern "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 57struct 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 109bool 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 130bool 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 203void CvCapture_Unicap::close() { 204 if(device_initialized) 205 shutdownDevice(); 206} 207 208bool 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 236IplImage * 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 244double 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 272bool 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 311bool 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 325CvCapture * 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