• 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 "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         
00129         pthread_mutex_lock(&requestMutex);
00130         
00131         // do a deep copy of the burst
00132         streamingShot = burst;
00133         
00134         // clone the ids
00135         for (size_t i = 0; i < burst.size(); i++) {
00136             streamingShot[i].id = burst[i].id;
00137         }
00138         pthread_mutex_unlock(&requestMutex);
00139 
00140         start();
00141         if (daemon->requestQueue.size() == 0) capture(streamingShot);
00142     }
00143     
00144     bool Sensor::streaming() {
00145         return streamingShot.size() > 0;
00146     }
00147     
00148     void Sensor::stopStreaming() {
00149         pthread_mutex_lock(&requestMutex);
00150         streamingShot.clear();
00151         pthread_mutex_unlock(&requestMutex);
00152     }
00153         
00154     Frame Sensor::getFrame() {
00155         if (!daemon) {
00156             Frame invalid;
00157             error(Event::SensorStoppedError, "Can't request a frame before calling capture or stream\n");
00158             return invalid;
00159         }        
00160         Frame frame(daemon->frameQueue.pull());
00161         FCam::Sensor::tagFrame(frame); // Use the base class tagFrame
00162         for (size_t i = 0; i < devices.size(); i++) {
00163             devices[i]->tagFrame(frame);
00164         }
00165         decShotsPending();
00166         return frame;
00167     }
00168     
00169     int Sensor::rollingShutterTime(const Shot &s) const {
00170         // TODO: put better numbers here
00171         if (s.image.height() > 960) return 77000;
00172         else return 33000;
00173     }
00174     
00175     // the Daemon calls this when it's time for new frames to be queued up
00176     void Sensor::generateRequest() {
00177         pthread_mutex_lock(&requestMutex);
00178         if (streamingShot.size()) {
00179             for (size_t i = 0; i < streamingShot.size(); i++) {
00180                 _Frame *f = new _Frame;
00181                 f->_shot = streamingShot[i];                
00182                 f->_shot.id = streamingShot[i].id;                
00183                 shotsPending_++;
00184                 daemon->requestQueue.push(f);
00185             }
00186         }
00187         pthread_mutex_unlock(&requestMutex);
00188 
00189     }
00190     
00191     void Sensor::enforceDropPolicy() {
00192         if (!daemon) return;
00193         daemon->setDropPolicy(dropPolicy, frameLimit);
00194     }
00195     
00196     int Sensor::framesPending() const {
00197         if (!daemon) return 0;
00198         return daemon->frameQueue.size();
00199     }
00200     
00201     int Sensor::shotsPending() const {
00202         return shotsPending_;
00203     }
00204 
00205     void Sensor::decShotsPending() {
00206         pthread_mutex_lock(&requestMutex);
00207         shotsPending_--;
00208         pthread_mutex_unlock(&requestMutex);        
00209     }
00210         
00211     unsigned short Sensor::minRawValue() const {return Platform::minRawValue;}
00212     unsigned short Sensor::maxRawValue() const {return Platform::maxRawValue;}
00213         
00214     BayerPattern Sensor::bayerPattern() const {return Platform::bayerPattern;}        
00215 
00216     const std::string &Sensor::manufacturer() const {return Platform::manufacturer;}
00217 
00218     const std::string &Sensor::model() const {return Platform::model;}        
00219 
00220     void Sensor::rawToRGBColorMatrix(int kelvin, float *matrix) const {
00221         // call the static platform implementation
00222         Platform::rawToRGBColorMatrix(kelvin, matrix);
00223     }
00224 
00225 
00226 }}

Generated on Thu Jul 22 2010 17:50:33 for FCam by  doxygen 1.7.1