• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

src/N900/Sensor.cpp

00001 #include <pthread.h>
00002 
00003 #include "FCam/Action.h"
00004 #include "FCam/N900/Sensor.h"
00005 
00006 #include "FCam/N900/Platform.h"
00007 #include "Daemon.h"
00008 #include "ButtonListener.h"
00009 #include "../Debug.h"
00010 
00011 
00012 
00013 namespace FCam { namespace N900 {
00014 
00015     Sensor::Sensor() : FCam::Sensor(), daemon(NULL), shotsPending_(0) {
00016         // make sure the N900 button listener is running
00017         
00018         // TODO: put this somewhere better?
00019         ButtonListener::instance();
00020         
00021         pthread_mutex_init(&requestMutex, NULL);
00022         
00023     }
00024     
00025     Sensor::~Sensor() {
00026         stop();
00027         pthread_mutex_destroy(&requestMutex);
00028     }
00029     
00030     void Sensor::start() {        
00031         if (daemon) return;
00032         daemon = new Daemon(this);
00033         if (streamingShot.size()) daemon->launchThreads();
00034     }
00035 
00036     void Sensor::stop() {
00037         dprintf(3, "Entering Sensor::stop\n"); 
00038         stopStreaming();
00039 
00040         if (!daemon) return;
00041 
00042         dprintf(3, "Cancelling outstanding requests\n");
00043 
00044         // Cancel as many requests as possible
00045         pthread_mutex_lock(&requestMutex);
00046         _Frame *req;
00047         while (daemon->requestQueue.tryPullBack(&req)) {
00048             delete req;
00049             shotsPending_--;
00050         }
00051         pthread_mutex_unlock(&requestMutex);        
00052 
00053         dprintf(3, "Discarding remaining frames\n");
00054 
00055         // Wait for the outstanding ones to complete
00056         while (shotsPending_) {
00057             delete daemon->frameQueue.pull();
00058             decShotsPending();
00059         }
00060 
00061         dprintf(3, "Deleting daemon\n"); 
00062 
00063         // Delete the daemon
00064         if (!daemon) return;
00065         delete daemon;
00066         daemon = NULL;
00067 
00068         dprintf(3, "Sensor stopped\n"); 
00069     }
00070     
00071     void Sensor::capture(const FCam::Shot &shot) {
00072         start();
00073         
00074         _Frame *f = new _Frame;
00075         
00076         // make a deep copy of the shot to attach to the request
00077         f->_shot = shot;        
00078         // clone the shot ID
00079         f->_shot.id = shot.id;
00080 
00081         // push the frame to the daemon
00082         pthread_mutex_lock(&requestMutex);
00083         shotsPending_++;
00084         daemon->requestQueue.push(f);
00085         pthread_mutex_unlock(&requestMutex);
00086 
00087         daemon->launchThreads();
00088     }
00089     
00090     void Sensor::capture(const std::vector<FCam::Shot> &burst) {
00091         start();              
00092 
00093         std::vector<_Frame *> frames;
00094         
00095         for (size_t i = 0; i < burst.size(); i++) {
00096             _Frame *f = new _Frame;
00097             f->_shot = burst[i];
00098             
00099             // clone the shot ID
00100             f->_shot.id = burst[i].id;
00101 
00102             frames.push_back(f); 
00103         }
00104 
00105         pthread_mutex_lock(&requestMutex);
00106         for (size_t i = 0; i < frames.size(); i++) {
00107             shotsPending_++;
00108             daemon->requestQueue.push(frames[i]);
00109         }
00110         pthread_mutex_unlock(&requestMutex);
00111 
00112         daemon->launchThreads();
00113     }
00114     
00115     void Sensor::stream(const FCam::Shot &shot) {
00116         pthread_mutex_lock(&requestMutex);
00117         streamingShot.clear();
00118         // this makes a deep copy of the shot
00119         streamingShot.push_back(shot);
00120         streamingShot[0].id = shot.id;
00121         pthread_mutex_unlock(&requestMutex);
00122 
00123         start();
00124         if (daemon->requestQueue.size() == 0) capture(streamingShot);
00125     }
00126     
00127     void Sensor::stream(const std::vector<FCam::Shot> &burst) {
00128         pthread_mutex_lock(&requestMutex);
00129         
00130         // do a deep copy of the burst
00131         streamingShot = burst;
00132         
00133         // clone the ids 
00134         for (size_t i = 0; i < burst.size(); i++) {
00135             streamingShot[i].id = burst[i].id;
00136         }
00137         pthread_mutex_unlock(&requestMutex);
00138 
00139         start();
00140         if (daemon->requestQueue.size() == 0) capture(streamingShot);
00141     }
00142     
00143     bool Sensor::streaming() {
00144         return streamingShot.size() > 0;
00145     }
00146     
00147     void Sensor::stopStreaming() {
00148         pthread_mutex_lock(&requestMutex);
00149         streamingShot.clear();
00150         pthread_mutex_unlock(&requestMutex);
00151     }
00152         
00153     Frame Sensor::getFrame() {
00154         if (!daemon) {
00155             Frame invalid;
00156             error(Event::SensorStoppedError, "Can't request a frame before calling capture or stream\n");
00157             return invalid;
00158         }        
00159         Frame frame(daemon->frameQueue.pull());
00160         FCam::Sensor::tagFrame(frame); // Use the base class tagFrame
00161         for (size_t i = 0; i < devices.size(); i++) {
00162             devices[i]->tagFrame(frame);
00163         }
00164         decShotsPending();
00165         return frame;
00166     }
00167     
00168     int Sensor::rollingShutterTime(const Shot &s) const {
00169         // TODO: put better numbers here
00170         if (s.image.height() > 960) return 77000;
00171         else return 33000;
00172     }
00173     
00174     // the Daemon calls this when it's time for new frames to be queued up
00175     void Sensor::generateRequest() {
00176         pthread_mutex_lock(&requestMutex);
00177         if (streamingShot.size()) {
00178             for (size_t i = 0; i < streamingShot.size(); i++) {
00179                 _Frame *f = new _Frame;
00180                 f->_shot = streamingShot[i];                
00181                 f->_shot.id = streamingShot[i].id;                
00182                 shotsPending_++;
00183                 daemon->requestQueue.push(f);
00184             }
00185         }
00186         pthread_mutex_unlock(&requestMutex);
00187 
00188     }
00189     
00190     void Sensor::enforceDropPolicy() {
00191         if (!daemon) return;
00192         daemon->setDropPolicy(dropPolicy, frameLimit);
00193     }
00194     
00195     int Sensor::framesPending() const {
00196         if (!daemon) return 0;
00197         return daemon->frameQueue.size();
00198     }
00199     
00200     int Sensor::shotsPending() const {
00201         return shotsPending_;
00202     }
00203 
00204     void Sensor::decShotsPending() {
00205         pthread_mutex_lock(&requestMutex);
00206         shotsPending_--;
00207         pthread_mutex_unlock(&requestMutex);        
00208     }
00209         
00210 }}

Generated on Mon Aug 16 2010 14:25:45 for FCam by  doxygen 1.7.1