/*M/////////////////////////////////////////////////////////////////////////////////////// // // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. // // By downloading, copying, installing or using the software you agree to this license. // If you do not agree to this license, do not download, install, // copy or use the software. // // // Intel License Agreement // For Open Source Computer Vision Library // // Copyright (C) 2008, Xavier Delacour, all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met: // // * Redistribution's of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // * Redistribution's in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // * The name of Intel Corporation may not be used to endorse or promote products // derived from this software without specific prior written permission. // // This software is provided by the copyright holders and contributors "as is" and // any express or implied warranties, including, but not limited to, the implied // warranties of merchantability and fitness for a particular purpose are disclaimed. // In no event shall the Intel Corporation or contributors be liable for any direct, // indirect, incidental, special, exemplary, or consequential damages // (including, but not limited to, procurement of substitute goods or services; // loss of use, data, or profits; or business interruption) however caused // and on any theory of liability, whether in contract, strict liability, // or tort (including negligence or otherwise) arising in any way out of // the use of this software, even if advised of the possibility of such damage. // //M*/ // 2008-04-27 Xavier Delacour #include "precomp.hpp" #include #include extern "C" { #include } #ifdef NDEBUG #define CV_WARN(message) #else #define CV_WARN(message) fprintf(stderr, "warning: %s (%s:%d)\n", message, __FILE__, __LINE__) #endif struct CvCapture_Unicap : public CvCapture { CvCapture_Unicap() { init(); } virtual ~CvCapture_Unicap() { close(); } virtual bool open( int index ); virtual void close(); virtual double getProperty(int) const CV_OVERRIDE; virtual bool setProperty(int, double) CV_OVERRIDE; virtual bool grabFrame() CV_OVERRIDE; virtual IplImage* retrieveFrame(int) CV_OVERRIDE; virtual int getCaptureDomain() CV_OVERRIDE { return CV_CAP_UNICAP; } bool shutdownDevice(); bool initDevice(); void init() { device_initialized = false; desired_format = 0; desired_size = cvSize(0,0); convert_rgb = false; handle = 0; memset( &device, 0, sizeof(device) ); memset( &format_spec, 0, sizeof(format_spec) ); memset( &format, 0, sizeof(format) ); memset( &raw_buffer, 0, sizeof(raw_buffer) ); memset( &buffer, 0, sizeof(buffer) ); raw_frame = frame = 0; } bool device_initialized; int desired_device; int desired_format; CvSize desired_size; bool convert_rgb; unicap_handle_t handle; unicap_device_t device; unicap_format_t format_spec; unicap_format_t format; unicap_data_buffer_t raw_buffer; unicap_data_buffer_t buffer; IplImage *raw_frame; IplImage *frame; }; bool CvCapture_Unicap::shutdownDevice() { bool result = false; CV_FUNCNAME("CvCapture_Unicap::shutdownDevice"); __BEGIN__; if (!SUCCESS(unicap_stop_capture(handle))) CV_ERROR(CV_StsError, "unicap: failed to stop capture on device\n"); if (!SUCCESS(unicap_close(handle))) CV_ERROR(CV_StsError, "unicap: failed to close the device\n"); cvReleaseImage(&raw_frame); cvReleaseImage(&frame); device_initialized = false; result = true; __END__; return result; } bool CvCapture_Unicap::initDevice() { bool result = false; CV_FUNCNAME("CvCapture_Unicap::initDevice"); __BEGIN__; if (device_initialized && !shutdownDevice()) return false; if(!SUCCESS(unicap_enumerate_devices(NULL, &device, desired_device))) CV_ERROR(CV_StsError, "unicap: failed to get info for device\n"); if(!SUCCESS(unicap_open( &handle, &device))) CV_ERROR(CV_StsError, "unicap: failed to open device\n"); unicap_void_format(&format_spec); if (!SUCCESS(unicap_enumerate_formats(handle, &format_spec, &format, desired_format))) { shutdownDevice(); CV_ERROR(CV_StsError, "unicap: failed to get video format\n"); } int i; if (format.sizes) { for (i = format.size_count - 1; i > 0; i--) if (format.sizes[i].width == desired_size.width && format.sizes[i].height == desired_size.height) break; format.size.width = format.sizes[i].width; format.size.height = format.sizes[i].height; } if (!SUCCESS(unicap_set_format(handle, &format))) { shutdownDevice(); CV_ERROR(CV_StsError, "unicap: failed to set video format\n"); } memset(&raw_buffer, 0x0, sizeof(unicap_data_buffer_t)); raw_frame = cvCreateImage(cvSize(format.size.width, format.size.height), 8, format.bpp / 8); memcpy(&raw_buffer.format, &format, sizeof(raw_buffer.format)); raw_buffer.data = (unsigned char*)raw_frame->imageData; raw_buffer.buffer_size = format.size.width * format.size.height * format.bpp / 8; memset(&buffer, 0x0, sizeof(unicap_data_buffer_t)); memcpy(&buffer.format, &format, sizeof(buffer.format)); buffer.format.fourcc = UCIL_FOURCC('B','G','R','3'); buffer.format.bpp = 24; // * todo support greyscale output // buffer.format.fourcc = UCIL_FOURCC('G','R','E','Y'); // buffer.format.bpp = 8; frame = cvCreateImage(cvSize(buffer.format.size.width, buffer.format.size.height), 8, buffer.format.bpp / 8); buffer.data = (unsigned char*)frame->imageData; buffer.buffer_size = buffer.format.size.width * buffer.format.size.height * buffer.format.bpp / 8; if(!SUCCESS(unicap_start_capture(handle))) { shutdownDevice(); CV_ERROR(CV_StsError, "unicap: failed to start capture on device\n"); } device_initialized = true; result = true; __END__; return result; } void CvCapture_Unicap::close() { if(device_initialized) shutdownDevice(); } bool CvCapture_Unicap::grabFrame() { bool result = false; CV_FUNCNAME("CvCapture_Unicap::grabFrame"); __BEGIN__; unicap_data_buffer_t *returned_buffer; int retry_count = 100; while (retry_count--) { if(!SUCCESS(unicap_queue_buffer(handle, &raw_buffer))) CV_ERROR(CV_StsError, "unicap: failed to queue a buffer on device\n"); if(SUCCESS(unicap_wait_buffer(handle, &returned_buffer))) { result = true; EXIT; } CV_WARN("unicap: failed to wait for buffer on device\n"); usleep(100 * 1000); } __END__; return result; } IplImage * CvCapture_Unicap::retrieveFrame(int) { if (convert_rgb) { ucil_convert_buffer(&buffer, &raw_buffer); return frame; } return raw_frame; } double CvCapture_Unicap::getProperty(int id) const { switch (id) { case CV_CAP_PROP_POS_MSEC: break; case CV_CAP_PROP_POS_FRAMES: break; case CV_CAP_PROP_POS_AVI_RATIO: break; case CV_CAP_PROP_FRAME_WIDTH: return desired_size.width; case CV_CAP_PROP_FRAME_HEIGHT: return desired_size.height; case CV_CAP_PROP_FPS: break; case CV_CAP_PROP_FOURCC: break; case CV_CAP_PROP_FRAME_COUNT: break; case CV_CAP_PROP_FORMAT: return desired_format; case CV_CAP_PROP_MODE: break; case CV_CAP_PROP_BRIGHTNESS: break; case CV_CAP_PROP_CONTRAST: break; case CV_CAP_PROP_SATURATION: break; case CV_CAP_PROP_HUE: break; case CV_CAP_PROP_GAIN: break; case CV_CAP_PROP_CONVERT_RGB: return convert_rgb; } return 0; } bool CvCapture_Unicap::setProperty(int id, double value) { bool reinit = false; switch (id) { case CV_CAP_PROP_POS_MSEC: break; case CV_CAP_PROP_POS_FRAMES: break; case CV_CAP_PROP_POS_AVI_RATIO: break; case CV_CAP_PROP_FRAME_WIDTH: desired_size.width = (int)value; reinit = true; break; case CV_CAP_PROP_FRAME_HEIGHT: desired_size.height = (int)value; reinit = true; break; case CV_CAP_PROP_FPS: break; case CV_CAP_PROP_FOURCC: break; case CV_CAP_PROP_FRAME_COUNT: break; case CV_CAP_PROP_FORMAT: desired_format = id; reinit = true; break; case CV_CAP_PROP_MODE: break; case CV_CAP_PROP_BRIGHTNESS: break; case CV_CAP_PROP_CONTRAST: break; case CV_CAP_PROP_SATURATION: break; case CV_CAP_PROP_HUE: break; case CV_CAP_PROP_GAIN: break; case CV_CAP_PROP_CONVERT_RGB: convert_rgb = value != 0; break; } if (reinit && !initDevice()) return false; return true; } bool CvCapture_Unicap::open(int index) { close(); device_initialized = false; desired_device = index < 0 ? 0 : index; desired_format = 0; desired_size = cvSize(320, 240); convert_rgb = true; return initDevice(); } CvCapture * cvCreateCameraCapture_Unicap(const int index) { CvCapture_Unicap *cap = new CvCapture_Unicap; if( cap->open(index) ) return cap; delete cap; return 0; }