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 }