shmem.cpp
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 /** @class SharedMemoryCamera <cams/shmem.h> 00036 * Shared memory camera. 00037 * Camera to retrieve images from a shared memory segment. 00038 * 00039 * The camera can operate in a so-called deep-copy mode. In this mode a 00040 * local internal buffer is created of the size of the image. On capture() 00041 * the image is copied from the shared memory buffer to the local buffer 00042 * with the shared memory segment locked for reading. This can be used if 00043 * the image writing and the image reading processess run asynchronously. 00044 * While locking would suffice the copying will account for only short 00045 * locking times so that the interference between the two processes is 00046 * minimal. 00047 * 00048 * @author Tim Niemueller 00049 */ 00050 00051 /** Constructor. 00052 * @param image_id image ID to open 00053 * @param deep_copy true to operate in deep-copy mode, false otherwise 00054 */ 00055 SharedMemoryCamera::SharedMemoryCamera(const char *image_id, bool deep_copy) 00056 { 00057 __image_id = strdup(image_id); 00058 __deep_copy = deep_copy; 00059 00060 try { 00061 init(); 00062 } catch (Exception &e) { 00063 free(__image_id); 00064 __image_id = NULL; 00065 throw; 00066 } 00067 } 00068 00069 00070 /** Constructor. 00071 * Take configuration data from camera argument parser. The following 00072 * options are supported. 00073 * - image_id=ID, where ID is the image ID 00074 * @param cap camera argument parser 00075 */ 00076 SharedMemoryCamera::SharedMemoryCamera(const CameraArgumentParser *cap) 00077 { 00078 __image_id = NULL; 00079 __deep_copy = false; 00080 00081 if ( cap->has("image_id") ) { 00082 __image_id = strdup(cap->get("image_id").c_str()); 00083 } 00084 else throw MissingParameterException("The parameter 'image_id' is required"); 00085 00086 if ( cap->has("deep_copy") ) { 00087 __deep_copy = (strcasecmp(cap->get("deep_copy").c_str(), "true") == 0); 00088 } 00089 00090 try { 00091 init(); 00092 } catch (Exception &e) { 00093 free(__image_id); 00094 __image_id = NULL; 00095 throw; 00096 } 00097 } 00098 00099 00100 /** Destructor. */ 00101 SharedMemoryCamera::~SharedMemoryCamera() 00102 { 00103 free(__image_id); 00104 if ( __deep_buffer != NULL ) { 00105 free( __deep_buffer ); 00106 } 00107 delete __shm_buffer; 00108 delete __capture_time; 00109 } 00110 00111 00112 void 00113 SharedMemoryCamera::init() 00114 { 00115 __deep_buffer = NULL; 00116 __capture_time = NULL; 00117 try { 00118 __shm_buffer = new SharedMemoryImageBuffer(__image_id); 00119 if ( __deep_copy ) { 00120 __deep_buffer = (unsigned char *)malloc(__shm_buffer->data_size()); 00121 if ( ! __deep_buffer ) { 00122 throw OutOfMemoryException("SharedMemoryCamera: Cannot allocate deep buffer"); 00123 } 00124 } 00125 __opened = true; 00126 } catch (Exception &e) { 00127 e.append("Failed to open shared memory image"); 00128 throw; 00129 } 00130 __capture_time = new fawkes::Time(0, 0); 00131 } 00132 00133 void 00134 SharedMemoryCamera::open() 00135 { 00136 } 00137 00138 00139 void 00140 SharedMemoryCamera::start() 00141 { 00142 } 00143 00144 void 00145 SharedMemoryCamera::stop() 00146 { 00147 } 00148 00149 void 00150 SharedMemoryCamera::print_info() 00151 { 00152 } 00153 00154 void 00155 SharedMemoryCamera::capture() 00156 { 00157 if ( __deep_copy ) { 00158 __shm_buffer->lock_for_read(); 00159 memcpy(__deep_buffer, __shm_buffer->buffer(), __shm_buffer->data_size()); 00160 __capture_time->set_time(__shm_buffer->capture_time()); 00161 __shm_buffer->unlock(); 00162 } 00163 else __capture_time->set_time(__shm_buffer->capture_time()); 00164 } 00165 00166 unsigned char* 00167 SharedMemoryCamera::buffer() 00168 { 00169 if ( __deep_copy ) { 00170 return __deep_buffer; 00171 } else { 00172 return __shm_buffer->buffer(); 00173 } 00174 } 00175 00176 unsigned int 00177 SharedMemoryCamera::buffer_size() 00178 { 00179 return colorspace_buffer_size(__shm_buffer->colorspace(), 00180 __shm_buffer->width(), 00181 __shm_buffer->height() ); 00182 } 00183 00184 void 00185 SharedMemoryCamera::close() 00186 { 00187 } 00188 00189 void 00190 SharedMemoryCamera::dispose_buffer() 00191 { 00192 } 00193 00194 unsigned int 00195 SharedMemoryCamera::pixel_width() 00196 { 00197 return __shm_buffer->width(); 00198 } 00199 00200 unsigned int 00201 SharedMemoryCamera::pixel_height() 00202 { 00203 return __shm_buffer->height(); 00204 } 00205 00206 00207 colorspace_t 00208 SharedMemoryCamera::colorspace() 00209 { 00210 return __shm_buffer->colorspace(); 00211 } 00212 00213 00214 fawkes::Time * 00215 SharedMemoryCamera::capture_time() 00216 { 00217 return __capture_time; 00218 } 00219 00220 00221 void 00222 SharedMemoryCamera::flush() 00223 { 00224 } 00225 00226 00227 /** Get the shared memory image buffer. 00228 * @return shared memory image buffer used to access image 00229 */ 00230 SharedMemoryImageBuffer * 00231 SharedMemoryCamera::shared_memory_image_buffer() 00232 { 00233 return __shm_buffer; 00234 } 00235 00236 00237 bool 00238 SharedMemoryCamera::ready() 00239 { 00240 return __opened; 00241 } 00242 00243 00244 void 00245 SharedMemoryCamera::set_image_number(unsigned int n) 00246 { 00247 // ignore for now 00248 } 00249 00250 00251 /** Lock image for reading. 00252 * Aquire the lock to read images. 00253 */ 00254 void 00255 SharedMemoryCamera::lock_for_read() 00256 { 00257 __shm_buffer->lock_for_read(); 00258 } 00259 00260 00261 /** Try to lock for reading. 00262 * @return true if the lock has been aquired, false otherwise 00263 */ 00264 bool 00265 SharedMemoryCamera::try_lock_for_read() 00266 { 00267 return __shm_buffer->try_lock_for_read(); 00268 } 00269 00270 00271 /** Lock image for writing. 00272 * Aquire the lock to write images. 00273 */ 00274 void 00275 SharedMemoryCamera::lock_for_write() 00276 { 00277 __shm_buffer->lock_for_write(); 00278 } 00279 00280 00281 /** Try to lock for reading. 00282 * @return true if the lock has been aquired, false otherwise 00283 */ 00284 bool 00285 SharedMemoryCamera::try_lock_for_write() 00286 { 00287 return __shm_buffer->try_lock_for_write(); 00288 } 00289 00290 00291 /** Unlock buffer. */ 00292 void 00293 SharedMemoryCamera::unlock() 00294 { 00295 __shm_buffer->unlock(); 00296 }

