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 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

Generated on 1 Mar 2011 for Fawkes API by  doxygen 1.6.1