Fawkes API
Fawkes Development Version
|
00001 /*************************************************************************** 00002 * shmem.cpp - Implementation to access images in shared memory 00003 * 00004 * Created: Thu Jan 12 19:43:05 2006 00005 * Copyright 2005-2009 Tim Niemueller [www.niemueller.de] 00006 * 00007 ****************************************************************************/ 00008 00009 /* This program is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. A runtime exception applies to 00013 * this software (see LICENSE.GPL_WRE file mentioned below for details). 00014 * 00015 * This program is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 * GNU Library General Public License for more details. 00019 * 00020 * Read the full text in the LICENSE.GPL_WRE file in the doc directory. 00021 */ 00022 00023 #include <core/exception.h> 00024 #include <core/exceptions/system.h> 00025 #include <core/exceptions/software.h> 00026 #include <cams/shmem.h> 00027 #include <fvutils/writers/fvraw.h> 00028 #include <fvutils/system/camargp.h> 00029 00030 #include <cstring> 00031 #include <cstdlib> 00032 00033 using namespace fawkes; 00034 00035 namespace firevision { 00036 #if 0 /* just to make Emacs auto-indent happy */ 00037 } 00038 #endif 00039 00040 /** @class SharedMemoryCamera <cams/shmem.h> 00041 * Shared memory camera. 00042 * Camera to retrieve images from a shared memory segment. 00043 * 00044 * The camera can operate in a so-called deep-copy mode. In this mode a 00045 * local internal buffer is created of the size of the image. On capture() 00046 * the image is copied from the shared memory buffer to the local buffer 00047 * with the shared memory segment locked for reading. This can be used if 00048 * the image writing and the image reading processess run asynchronously. 00049 * While locking would suffice the copying will account for only short 00050 * locking times so that the interference between the two processes is 00051 * minimal. 00052 * 00053 * @author Tim Niemueller 00054 */ 00055 00056 /** Constructor. 00057 * @param image_id image ID to open 00058 * @param deep_copy true to operate in deep-copy mode, false otherwise 00059 */ 00060 SharedMemoryCamera::SharedMemoryCamera(const char *image_id, bool deep_copy) 00061 { 00062 __image_id = strdup(image_id); 00063 __deep_copy = deep_copy; 00064 00065 try { 00066 init(); 00067 } catch (Exception &e) { 00068 free(__image_id); 00069 __image_id = NULL; 00070 throw; 00071 } 00072 } 00073 00074 00075 /** Constructor. 00076 * Take configuration data from camera argument parser. The following 00077 * options are supported. 00078 * - image_id=ID, where ID is the image ID 00079 * @param cap camera argument parser 00080 */ 00081 SharedMemoryCamera::SharedMemoryCamera(const CameraArgumentParser *cap) 00082 { 00083 __image_id = NULL; 00084 __deep_copy = false; 00085 00086 if ( cap->has("image_id") ) { 00087 __image_id = strdup(cap->get("image_id").c_str()); 00088 } 00089 else throw MissingParameterException("The parameter 'image_id' is required"); 00090 00091 if ( cap->has("deep_copy") ) { 00092 __deep_copy = (strcasecmp(cap->get("deep_copy").c_str(), "true") == 0); 00093 } 00094 00095 try { 00096 init(); 00097 } catch (Exception &e) { 00098 free(__image_id); 00099 __image_id = NULL; 00100 throw; 00101 } 00102 } 00103 00104 00105 /** Destructor. */ 00106 SharedMemoryCamera::~SharedMemoryCamera() 00107 { 00108 free(__image_id); 00109 if ( __deep_buffer != NULL ) { 00110 free( __deep_buffer ); 00111 } 00112 delete __shm_buffer; 00113 delete __capture_time; 00114 } 00115 00116 00117 void 00118 SharedMemoryCamera::init() 00119 { 00120 __deep_buffer = NULL; 00121 __capture_time = NULL; 00122 try { 00123 __shm_buffer = new SharedMemoryImageBuffer(__image_id); 00124 if ( __deep_copy ) { 00125 __deep_buffer = (unsigned char *)malloc(__shm_buffer->data_size()); 00126 if ( ! __deep_buffer ) { 00127 throw OutOfMemoryException("SharedMemoryCamera: Cannot allocate deep buffer"); 00128 } 00129 } 00130 __opened = true; 00131 } catch (Exception &e) { 00132 e.append("Failed to open shared memory image"); 00133 throw; 00134 } 00135 __capture_time = new fawkes::Time(0, 0); 00136 } 00137 00138 void 00139 SharedMemoryCamera::open() 00140 { 00141 } 00142 00143 00144 void 00145 SharedMemoryCamera::start() 00146 { 00147 } 00148 00149 void 00150 SharedMemoryCamera::stop() 00151 { 00152 } 00153 00154 void 00155 SharedMemoryCamera::print_info() 00156 { 00157 } 00158 00159 void 00160 SharedMemoryCamera::capture() 00161 { 00162 if ( __deep_copy ) { 00163 __shm_buffer->lock_for_read(); 00164 memcpy(__deep_buffer, __shm_buffer->buffer(), __shm_buffer->data_size()); 00165 __capture_time->set_time(__shm_buffer->capture_time()); 00166 __shm_buffer->unlock(); 00167 } 00168 else __capture_time->set_time(__shm_buffer->capture_time()); 00169 } 00170 00171 unsigned char* 00172 SharedMemoryCamera::buffer() 00173 { 00174 if ( __deep_copy ) { 00175 return __deep_buffer; 00176 } else { 00177 return __shm_buffer->buffer(); 00178 } 00179 } 00180 00181 unsigned int 00182 SharedMemoryCamera::buffer_size() 00183 { 00184 return colorspace_buffer_size(__shm_buffer->colorspace(), 00185 __shm_buffer->width(), 00186 __shm_buffer->height() ); 00187 } 00188 00189 void 00190 SharedMemoryCamera::close() 00191 { 00192 } 00193 00194 void 00195 SharedMemoryCamera::dispose_buffer() 00196 { 00197 } 00198 00199 unsigned int 00200 SharedMemoryCamera::pixel_width() 00201 { 00202 return __shm_buffer->width(); 00203 } 00204 00205 unsigned int 00206 SharedMemoryCamera::pixel_height() 00207 { 00208 return __shm_buffer->height(); 00209 } 00210 00211 00212 colorspace_t 00213 SharedMemoryCamera::colorspace() 00214 { 00215 return __shm_buffer->colorspace(); 00216 } 00217 00218 00219 fawkes::Time * 00220 SharedMemoryCamera::capture_time() 00221 { 00222 return __capture_time; 00223 } 00224 00225 00226 void 00227 SharedMemoryCamera::flush() 00228 { 00229 } 00230 00231 00232 /** Get the shared memory image buffer. 00233 * @return shared memory image buffer used to access image 00234 */ 00235 SharedMemoryImageBuffer * 00236 SharedMemoryCamera::shared_memory_image_buffer() 00237 { 00238 return __shm_buffer; 00239 } 00240 00241 00242 bool 00243 SharedMemoryCamera::ready() 00244 { 00245 return __opened; 00246 } 00247 00248 00249 void 00250 SharedMemoryCamera::set_image_number(unsigned int n) 00251 { 00252 // ignore for now 00253 } 00254 00255 00256 /** Lock image for reading. 00257 * Aquire the lock to read images. 00258 */ 00259 void 00260 SharedMemoryCamera::lock_for_read() 00261 { 00262 __shm_buffer->lock_for_read(); 00263 } 00264 00265 00266 /** Try to lock for reading. 00267 * @return true if the lock has been aquired, false otherwise 00268 */ 00269 bool 00270 SharedMemoryCamera::try_lock_for_read() 00271 { 00272 return __shm_buffer->try_lock_for_read(); 00273 } 00274 00275 00276 /** Lock image for writing. 00277 * Aquire the lock to write images. 00278 */ 00279 void 00280 SharedMemoryCamera::lock_for_write() 00281 { 00282 __shm_buffer->lock_for_write(); 00283 } 00284 00285 00286 /** Try to lock for reading. 00287 * @return true if the lock has been aquired, false otherwise 00288 */ 00289 bool 00290 SharedMemoryCamera::try_lock_for_write() 00291 { 00292 return __shm_buffer->try_lock_for_write(); 00293 } 00294 00295 00296 /** Unlock buffer. */ 00297 void 00298 SharedMemoryCamera::unlock() 00299 { 00300 __shm_buffer->unlock(); 00301 } 00302 00303 } // end namespace firevision