Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

phPipeline.cpp

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------
00002     Phission :
00003         Realtime Vision Processing System
00004 
00005     Copyright (C) 2003-2006 Philip D.S. Thoren (pthoren@cs.uml.edu)
00006     University of Massachusetts at Lowell,
00007     Laboratory for Artificial Intelligence and Robotics
00008 
00009     This file is part of Phission.
00010 
00011     Phission is free software; you can redistribute it and/or modify
00012     it under the terms of the GNU Lesser General Public License as published by
00013     the Free Software Foundation; either version 2 of the License, or
00014     (at your option) any later version.
00015 
00016     Phission is distributed in the hope that it will be useful,
00017     but WITHOUT ANY WARRANTY; without even the implied warranty of
00018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019     GNU Lesser General Public License for more details.
00020 
00021     You should have received a copy of the GNU Lesser General Public License
00022     along with Phission; if not, write to the Free Software
00023     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024 
00025  ---------------------------------------------------------------------------*/
00026 #ifdef HAVE_CONFIG_H
00027     #include <phissionconfig.h>
00028 #endif
00029 
00030 #include <phStandard.h>
00031 
00032 #include <phObject.h>
00033 #include <phMutex.h>
00034 #include <phRWLock.h>
00035 #include <phSemaphore.h>
00036 #include <phCondition.h>
00037 #include <phThread.h>
00038 #include <phTimeStamp.h>
00039 #include <phList.h>
00040 #include <phTimeInterval.h>
00041 #include <phObjectList.h>
00042 #include <phLiveObject.h>
00043 #include <phDataObject.h>
00044 #include <phImage.h>
00045 #include <phFilter.h>
00046 
00047 #include <phPipeline.h>
00048 
00049 #include <phError.h>
00050 #include <phMemory.h>
00051 #include <phPrint.h>
00052 
00053 #define USE_SCHEDULING() 0
00054 
00055 /* ---------------------------------------------------------------------- */
00056 phPipeline::phPipeline() 
00057 {
00058     phFUNCTION("phPipeline::phPipeline")
00059 
00060     rc = this->lock();
00061     phPRINT_RC(rc, NULL, "this->lock");
00062 
00063     this->m_filterArray = NULL;
00064     this->m_filterCount = 0;
00065     
00066     this->m_liveSource      = NULL;
00067 
00068     /* Timing features */
00069     this->m_runtime.clear();
00070     this->m_averageRuntime.clear();
00071     this->m_timingEnabled       = 0;
00072     this->m_total_nsec          = 0.0;
00073     this->m_averageSamples      = 0;
00074     this->m_do_timing           = 0;
00075     
00076     this->setName("phPipeline");
00077     
00078     rc = this->unlock();
00079     phPRINT_RC(rc, NULL, "this->unlock");
00080 }
00081 
00082 /* ---------------------------------------------------------------------- */
00083 phPipeline::~phPipeline() 
00084 {
00085     phFUNCTION("phPipeline::~phPipeline")
00086 
00087     rc = this->lock();
00088     phPRINT_RC(rc, NULL, "this->lock");
00089 
00090     if (this->m_filterArray != NULL)
00091     {
00092         phFree(this->m_filterArray);
00093         this->m_filterCount = 0;
00094     }
00095 
00096     /* don't unlock, when phMutex is destroyed, anyone waiting will fail out,
00097      * but don't unlock till that time.... right? hmmmm */
00098 }
00099 
00100 /* ---------------------------------------------------------------------- */
00101 int phPipeline::setInputImage(phImage &newImage)
00102 {
00103     phFUNCTION("phPipeline::setImage")
00104 
00105     rc = this->lock();
00106     phPRINT_RC(rc, NULL, "this->lock");
00107 
00108     rc = this->m_inputImage.setImage(newImage);
00109     phCHECK_RC(rc,NULL,"m_inputImage.setImage");
00110 
00111     rc = this->unlock();
00112     phPRINT_RC(rc, NULL, "this->unlock");
00113 
00114     return phSUCCESS;
00115 error:
00116     rc = this->unlock();
00117     phPRINT_RC(rc, NULL, "this->unlock");
00118 
00119     return phFAIL;
00120 }
00121 
00122 # if 0
00123 
00124 This method is no longer useful the way data is being manipulated
00125 
00126 /* ---------------------------------------------------------------------- */
00127 int phPipeline::copyInputImage(phImage &copyto) {
00128     /* TODO: lock/unlock */
00129     
00130     if (((phImage&)this->getInputImage()).isNull() == 0)
00131         rc = copyto.setImage((phImage&)this->getInputImage());
00132     else
00133         rc = phFAIL;
00134 
00135     return rc;
00136 }
00137 #endif
00138 
00139 /* ---------------------------------------------------------------------- */
00140 int phPipeline::copyOutputImage(phImage &copyto) {
00141     int rc = 0;
00142     
00143     if (this->m_outputImage.isNull() == 0)
00144         rc = copyto.setImage(this->m_outputImage);
00145     else
00146         rc = phFAIL;
00147 
00148     return rc;
00149 }
00150 
00151 /* ---------------------------------------------------------------------- */
00152 const phImage &phPipeline::getInputImage() {
00153     if (this->m_liveSource == NULL)
00154         return this->m_inputImage;
00155     else
00156         return *((phImage *)this->m_liveSource);
00157 }
00158 
00159 /* ---------------------------------------------------------------------- */
00160 const phImage &phPipeline::getOutputImage() {
00161     return this->m_outputImage;
00162 }
00163 
00164 /* ---------------------------------------------------------------------- */
00165 int phPipeline::generateFilterArray()
00166 {
00167     phFUNCTION("phPipeline::generateFilterArray")
00168     int             locked      = 0;
00169     int             list_locked = 0;
00170     uint32_t        count       = 0;
00171     phObjectNode    *node       = NULL;
00172     phFilter        *filter     = NULL;
00173     uint32_t        i           = 0;
00174     
00175     phTHIS_LOCK(locked);
00176    
00177     phMUTEX_LOOSE_LOCK(this->m_filters,list_locked);
00178         
00179     count = this->m_filters.length();
00180     
00181     if (count <= 0)
00182     {
00183         if (this->m_filterArray != NULL)
00184         {
00185             phFree(this->m_filterArray);
00186         }
00187         this->m_filterCount = 0;
00188     }
00189     else
00190     {
00191         if (this->m_filterArray == NULL)
00192         {
00193             this->m_filterArray = (phFilter **)phCalloc(count,sizeof(phFilter*));
00194             phCHECK_NULLPTR(this->m_filterArray,"phCalloc","phCalloc failed.");
00195         }
00196         else if (this->m_filterCount != count)
00197         {
00198             this->m_filterArray = (phFilter **)phRealloc( this->m_filterArray,
00199                                                  count * sizeof(phFilter*));
00200             phCHECK_NULLPTR(this->m_filterArray,"phRealloc", "phRealloc failed.");
00201         }
00202         
00203         node = this->m_filters.getHeadObject();
00204         
00205         /*  Loop through all the displays in the list */
00206         while (node != NULL)
00207         {
00208             filter = (phFilter *)node->getObject();
00209        
00210             if (filter != NULL)
00211             {
00212                 this->m_filterArray[i] = filter;
00213                 this->m_filterArray[i]->setWorkspace(&this->m_workspaceImage);
00214                 this->m_filterArray[i]->setOriginal(&this->m_originalImage);
00215             }
00216 
00217             node = node->getNextObject();
00218             i++;
00219         }
00220         this->m_filterCount = count;
00221     }
00222 
00223     phMUTEX_LOOSE_UNLOCK(this->m_filters,list_locked);
00224 
00225     phTHIS_UNLOCK(locked);
00226     
00227     return phSUCCESS;
00228 error:
00229     phMUTEX_ERROR_UNLOCK(this->m_filters,list_locked);
00230 
00231     phTHIS_ERROR_UNLOCK(locked);
00232     
00233     return phFAIL;
00234 }
00235 /* ---------------------------------------------------------------------- */
00236 int phPipeline::add(phFilter *filter)
00237 {
00238     phFUNCTION("phPipeline::add")
00239     phObjectNode   *objnode = NULL;
00240     int             locked  = 0;
00241 
00242     if (filter == NULL) return phFAIL;
00243     
00244     phTHIS_LOCK(locked);
00245 
00246     /*
00247     if (this->isPipelineActive())
00248     {
00249         phCHECK_RC(-1, NULL, "The pipeline is active. Stop it first.");
00250     }
00251     */
00252     
00253     /* Push the object onto the end of the list */
00254     objnode = this->m_filters.pushObject(filter);
00255     phCHECK_PTR(objnode,NULL,"m_filters.pushObject");
00256     
00257     /* signal that the filter array needs to be regenerated */
00258     rc = this->m_generateSignal.post();
00259     phCHECK_RC(rc,NULL,"this->m_generateSignal.post");
00260         
00261     phTHIS_UNLOCK(locked);
00262 
00263     return phSUCCESS;
00264 error:
00265 
00266     phTHIS_ERROR_UNLOCK(locked);
00267 
00268     return phFAIL;
00269 }
00270 
00271 /* ---------------------------------------------------------------------- */
00272 int phPipeline::remove( phFilter *filter )
00273 {
00274     phFUNCTION("phPipeline::remove")
00275     phObject   *obj         = NULL;
00276     int         locked      = 0;
00277 
00278     if (filter == NULL) return phFAIL;
00279     
00280     phTHIS_LOCK(locked);
00281    
00282     /* Remove the object from the list */
00283     obj = this->m_filters.removeObject(filter);
00284     phCHECK_PTR(obj,NULL,"this->m_filters.removeObject");
00285 
00286     /* signal that the filter array needs to be regenerated */
00287     rc = this->m_generateSignal.post();
00288     phCHECK_RC(rc,NULL,"this->m_generateSignal.post");
00289     
00290     phTHIS_UNLOCK(locked);
00291     
00292     return phSUCCESS;
00293 error:
00294     phTHIS_ERROR_UNLOCK(locked);
00295 
00296     return phFAIL;
00297 }
00298 
00299 /* ---------------------------------------------------------------------- */
00300 int phPipeline::empty()
00301 {
00302     phFUNCTION("phPipeline::empty")
00303     int locked = 0;
00304 
00305     phTHIS_LOCK(locked);
00306 
00307     /*
00308     if (this->isPipelineActive())
00309     {
00310         phCHECK_RC(-1, NULL,
00311            "The pipeline is active. Stop it first.");
00312     }
00313     */
00314     rc = this->m_filters.empty();
00315     phCHECK_RC(rc,NULL,"this->m_filters.empty()");
00316 
00317     /* signal that the filter array needs to be regenerated */
00318     rc = this->m_generateSignal.post();
00319     phCHECK_RC(rc,NULL,"this->m_generateSignal.post");
00320     
00321     phTHIS_UNLOCK(locked);
00322     
00323     return phSUCCESS;
00324 error:
00325     phTHIS_ERROR_UNLOCK(locked);
00326     
00327     return phFAIL;
00328 }
00329 
00330 /* ---------------------------------------------------------------------- */
00331 int phPipeline::query( phFilter *filter )
00332 {
00333     phFUNCTION("phPipeline::remove")
00334     phObjectNode   *objnode     = NULL;
00335     int             locked      = 0;
00336     int             exists      = 0;
00337 
00338     if (filter == NULL) return 0;
00339     
00340     phTHIS_LOCK(locked);
00341    
00342     /* Remove the object from the list */
00343     objnode = this->m_filters.findObject(filter);
00344    
00345     if (objnode != NULL) exists = 1;
00346     
00347     phTHIS_UNLOCK(locked);
00348     
00349     return exists;
00350 error:
00351     phTHIS_ERROR_UNLOCK(locked);
00352 
00353     return 0;
00354 }
00355 
00356 /* ---------------------------------------------------------------------- */
00357 int phPipeline::setLiveSourceInput(phLiveObject *img )
00358 {
00359     phFUNCTION("phPipeline::setLiveSourceInput")
00360     int locked = 0;
00361    
00362     phTHIS_LOCK(locked);
00363     
00364     if (img != this->m_liveSource)
00365     {
00366         if (img != NULL)
00367         {
00368             rc = img->isNamed("phImage");
00369             phCHECK_RC(rc,NULL,"Invalid phLiveObject input object type: %s",
00370                     img->getName());
00371         }
00372 
00373         this->m_liveSource      = img;
00374         
00375         rc = this->m_liveSourceSignal.post();
00376         phCHECK_RC(rc,NULL,"this->m_liveSourceSignal.post");
00377     }
00378     
00379     phTHIS_UNLOCK(locked);
00380 
00381     return phSUCCESS;
00382 error:
00383     phTHIS_ERROR_UNLOCK(locked);
00384     
00385     return phFAIL;
00386 }
00387 
00388 /* ---------------------------------------------------------------------- */
00389 phLiveObject  *phPipeline::getLiveSourceOutput() 
00390 {
00391     return &(this->m_outputImage);
00392 }
00393 
00394 /* ---------------------------------------------------------------------- */
00395 int phPipeline::setInput(phLiveObject *img )
00396 {
00397     return this->setLiveSourceInput(img);
00398 }
00399 
00400 /* ---------------------------------------------------------------------- */
00401 phLiveObject  *phPipeline::getOutput() 
00402 {
00403     return &(this->m_outputImage);
00404 }
00405 
00406 
00407 /* ---------------------------------------------------------------------- */
00408 int phPipeline::isPipelineActive() 
00409 { 
00410     return (this->isRunning() || (!this->threadStopped())) ? 1:0;
00411 }
00412 
00413 /* ---------------------------------------------------------------------- */
00414 int phPipeline::startPipeline()
00415 {
00416     return this->start();
00417 }
00418 
00419 /* ---------------------------------------------------------------------- */
00420 int phPipeline::stopPipeline()
00421 {
00422     return this->stop();
00423 }
00424 
00425 /* ---------------------------------------------------------------------- */
00426 int phPipeline::applyRuntime(phTimeStamp &runtime)
00427 {
00428     phFUNCTION("phPipeline::applyRuntime")
00429     int timelocked = 0;
00430     uintmax_t ave = 0;
00431     
00432     /* This is a convenience feature, we don't need to save every
00433      * timestamp, only the ones that don't contend with the mutex */
00434     phMUTEX_LOOSE_LOCK(this->m_timeLock,timelocked);
00435     
00436     if (rc == phSUCCESS)
00437     {
00438         this->m_runtime = runtime;
00439 
00440         this->m_total_nsec += runtime.getNanoseconds();
00441         this->m_averageSamples++;
00442         
00443         ave = (uintmax_t)(this->m_total_nsec / 
00444                           this->m_averageSamples);
00445         
00446         this->m_averageRuntime.setFromNanoseconds(ave);
00447             
00448         phMUTEX_LOOSE_UNLOCK(this->m_timeLock,timelocked);
00449     }
00450     
00451     return phSUCCESS;
00452 }
00453 
00454 
00455 /* ---------------------------------------------------------------------- */
00456 int phPipeline::enableTiming()
00457 {
00458     phFUNCTION("phPipeline::enableTiming")
00459     int locked = 0;
00460 
00461     phTHIS_LOOSE_LOCK(locked);
00462         
00463     if (!this->m_timingEnabled)
00464     {
00465         this->m_timingEnabled = 1;
00466         
00467         rc = this->m_timingEnabledSignal.post();
00468         phCHECK_RC(rc,NULL,"this->m_timingEnabledSignal.post");
00469     }
00470 
00471     phTHIS_LOOSE_UNLOCK(locked);
00472 
00473     return phSUCCESS;
00474 error:
00475     phTHIS_ERROR_UNLOCK(locked);
00476 
00477     return phFAIL;
00478 }
00479 
00480 /* ---------------------------------------------------------------------- */
00481 int phPipeline::disableTiming()
00482 {
00483     phFUNCTION("phPipeline::disableTiming")
00484     int locked = 0;
00485 
00486     phTHIS_LOOSE_LOCK(locked);
00487     
00488     if (this->m_timingEnabled)
00489     {
00490         this->m_timingEnabled = 0;
00491         
00492         rc = this->m_timingEnabledSignal.post();
00493         phCHECK_RC(rc,NULL,"this->m_timingEnabledSignal.post");
00494     }
00495     
00496     phTHIS_LOOSE_UNLOCK(locked);
00497 
00498     return phSUCCESS;
00499 error:
00500     phTHIS_ERROR_UNLOCK(locked);
00501 
00502     return phFAIL;
00503 }
00504 
00505 /* ---------------------------------------------------------------------- */
00506 int phPipeline::isTimingEnabled()
00507 {
00508     phFUNCTION("phPipeline::isTimingEnabled")
00509     int locked = 0;
00510     int retrc = 0;
00511 
00512     phTHIS_LOOSE_LOCK(locked);
00513         
00514     retrc = this->m_timingEnabled;
00515     
00516     phTHIS_LOOSE_UNLOCK(locked);
00517 
00518     return retrc;
00519 }
00520 
00521 /* ---------------------------------------------------------------------- */
00522 phTimeStamp phPipeline::runtime()
00523 {
00524     phFUNCTION("phPipeline::runtime")
00525     int timelocked = 0;
00526     phTimeStamp retval;
00527 
00528     phMUTEX_LOCK(this->m_timeLock,timelocked);
00529 
00530     retval = this->m_runtime;
00531 error:
00532     phMUTEX_ERROR_UNLOCK(this->m_timeLock,timelocked);
00533 
00534     return retval;
00535 }
00536 
00537 /* ---------------------------------------------------------------------- */
00538 phTimeStamp phPipeline::averageRuntime()
00539 {
00540     phFUNCTION("phPipeline::averageRuntime")
00541     int timelocked = 0;
00542     phTimeStamp retval;
00543 
00544     phMUTEX_LOCK(this->m_timeLock,timelocked);
00545 
00546     retval = this->m_averageRuntime;
00547 error:
00548     phMUTEX_ERROR_UNLOCK(this->m_timeLock,timelocked);
00549 
00550     return retval;
00551 }
00552 
00553 /* ---------------------------------------------------------------------- */
00554 uintmax_t phPipeline::averageSamples()
00555 {
00556     phFUNCTION("phPipeline::averageRuntime")
00557     int timelocked = 0;
00558     uintmax_t retval = 0;
00559 
00560     phMUTEX_LOCK(this->m_timeLock,timelocked);
00561 
00562     retval = this->m_averageSamples;
00563 error:
00564     phMUTEX_ERROR_UNLOCK(this->m_timeLock,timelocked);
00565 
00566     return retval;
00567 }
00568 
00569 /* ---------------------------------------------------------------------- */
00570 int phPipeline::resetAverage()
00571 {
00572     phFUNCTION("phPipeline::resetAverage")
00573     int timelocked = 0;
00574     phTimeStamp retval;
00575 
00576     phMUTEX_LOCK(this->m_timeLock,timelocked);
00577 
00578     this->m_averageRuntime.clear();
00579     this->m_averageSamples = 0;
00580     this->m_total_nsec = 0.0;
00581 error:
00582     phMUTEX_ERROR_UNLOCK(this->m_timeLock,timelocked);
00583 
00584     return phSUCCESS;
00585 }
00586 
00587 /* ---------------------------------------------------------------------- */
00588 int phPipeline::wakeup()
00589 {
00590     phFUNCTION("phPipeline::wakeup()")
00591 
00592     rc = this->m_inputImage.wakeup_clients();
00593     phPRINT_RC(rc,NULL,"this->m_inputImage.wakeup_clients()")
00594         
00595     rc = this->m_inputImage.wakeup_self();
00596     phPRINT_RC(rc,NULL,"this->m_inputImage.wakeup_self()")
00597         
00598     rc = this->m_workspaceImage.wakeup_self();
00599     phPRINT_RC(rc,NULL,"this->m_workspaceImage.wakeup_self()")
00600         
00601     rc = this->m_originalImage.wakeup_self();
00602     phPRINT_RC(rc,NULL,"this->m_originalImage.wakeup_self()")
00603 
00604     return phSUCCESS;
00605 }       
00606 
00607 /* ---------------------------------------------------------------------- */
00608 int phPipeline::checkSignals()
00609 {
00610     phFUNCTION("phPipeline::checkSignals")
00611     int locked  = 0;
00612     int g_rc    = phSUCCESS;
00613     int ls_rc   = phSUCCESS;
00614     int t_rc    = phSUCCESS;
00615         
00616     /* Check to see if there is a sem waiting... */
00617     g_rc = this->m_generateSignal.tryTake();
00618     phPRINT_RC(g_rc,NULL,"this->m_generateSignal.tryTake");
00619     
00620     /* Check to see if the live source has changed */
00621     ls_rc = this->m_liveSourceSignal.tryTake();
00622     phPRINT_RC(ls_rc,NULL,"this->m_liveSourceSignal.tryTake");
00623     
00624     /* Check to see if timing has been enabled changed */
00625     t_rc = this->m_timingEnabledSignal.tryTake();
00626     phPRINT_RC(t_rc,NULL,"this->m_timingEnabledSignal.tryTake");
00627    
00628     /* lock only if we're going to update something */
00629     if ((ls_rc == phSUCCESS) ||
00630         (t_rc == phSUCCESS))
00631     {
00632         phTHIS_LOOSE_LOCK(locked);
00633     }
00634     
00635     /* ... If the filter array should be generated, do it */
00636     if (g_rc == phSUCCESS)
00637     {
00638         rc = this->generateFilterArray();
00639         phPRINT_RC(rc,NULL,"this->generateFilterArray()");
00640     }
00641     
00642     /* Re-setup the live source image */
00643     if (ls_rc == phSUCCESS)
00644     {
00645         if (this->m_liveSource != NULL)
00646         {
00647             rc = this->m_inputImage.connect(this->m_liveSource);
00648             phPRINT_RC(rc,NULL,"m_inputImage.connect()");
00649         }
00650         else if (this->m_inputImage.isConnected())
00651         {
00652             rc = this->m_inputImage.disconnect();
00653             phPRINT_RC(rc,NULL,"m_inputImage.disconnect()");
00654         }
00655     }
00656 
00657     /* Set up the private timing variable */
00658     if (t_rc == phSUCCESS)
00659     {
00660         this->m_do_timing = this->m_timingEnabled;
00661     }
00662 
00663     /* Unlock if we locked because we were updating */
00664     if ((ls_rc == phSUCCESS) ||
00665         (t_rc == phSUCCESS))
00666     {
00667         phTHIS_LOOSE_UNLOCK(locked);
00668     }
00669 
00670     return phSUCCESS;
00671 }
00672 
00673 /* ---------------------------------------------------------------------- */
00674 int phPipeline::runFilters(int32_t use_input_image)
00675 {
00676     phFUNCTION("phPipeline::runFilters")
00677     int             locked          = 0;
00678     unsigned int    i               = 0;
00679     phLiveObject   *processInput    = NULL;
00680     phTimeInterval *runtime = new phTimeInterval("Pipeline Execution Time");
00681     phTimeStamp     elapsed;
00682 
00683     phTHIS_LOCK(locked);
00684 
00685     if (this->isPipelineActive())
00686     {
00687         phCHECK_RC(-1, NULL,"The pipeline is active. Stop it first.");
00688     }
00689 
00690     rc = this->checkSignals();
00691     phPRINT_RC(rc,NULL,"this->checkSignals()");
00692 
00693     /* Choose an input image:
00694      * The pipeline input as set through setInputImage(...) ...*/
00695     if (use_input_image == phPipeline_Input)
00696     {
00697         processInput = &(this->m_inputImage);
00698     }
00699     /* The live source input as set through setLiveSourceInput(...)... */
00700     else if ((use_input_image == phPipeline_LiveSource) &&
00701              (this->m_liveSource != NULL))
00702     {
00703         processInput = this->m_liveSource;
00704     }
00705     /* The input from setInputImage(...) if the live source is NULL,
00706      * or the input from the live source */
00707     else
00708     {
00709         processInput = ((this->m_liveSource != NULL) ?
00710                         this->m_liveSource :
00711                         &(this->m_inputImage));
00712     }
00713 
00714     /* processInput should never be NULL, but just be paranoid anyway */
00715     if (processInput != NULL)
00716     {
00717         rc = this->m_originalImage.setImage(*(phImage *)processInput);
00718         phCHECK_RC(rc,NULL,"m_originalImage.setImage failed.");
00719 
00720         rc = this->m_workspaceImage.setImage(this->m_originalImage);
00721         phCHECK_RC(rc,NULL,"m_workspaceImage.setImage failed.");
00722         
00723         if ((m_workspaceImage.isNull() == 0) && 
00724             (m_originalImage.isNull() == 0))
00725         {
00726             /* Get the timestamp for the start of the processing */
00727             if ((this->m_do_timing) && (this->m_filterCount > 0))
00728             {
00729                 runtime->start();
00730             }
00731             
00732             for (i = 0; i < this->m_filterCount; i++ )
00733             {
00734                 this->m_filterArray[i]->process();
00735             }
00736             
00737             /* Get the timestamp for the end of the processing loop */
00738             if ((this->m_do_timing) && (this->m_filterCount > 0))
00739             {
00740                 runtime->stop();
00741                 
00742                 elapsed = runtime->elapsed();
00743 
00744                 rc = this->applyRuntime(elapsed);
00745                 phPRINT_RC(rc,NULL,"this->applyRuntime");
00746             }
00747 
00748             rc = this->m_outputImage.swapImage( this->m_workspaceImage );
00749             phPRINT_RC(rc,NULL,"m_outputImage.swapImage");
00750         }
00751     }
00752     else 
00753     {
00754         goto error;
00755     }
00756 
00757     phDelete(runtime);
00758     
00759     phTHIS_UNLOCK(locked);
00760 
00761     return phSUCCESS;
00762 error:
00763     phDelete(runtime);
00764 
00765     phTHIS_ERROR_UNLOCK(locked);
00766 
00767     return phFAIL;
00768 }
00769 
00770 /* ---------------------------------------------------------------------- */
00771 int phPipeline::print()
00772 {
00773     phFUNCTION("phPipeline::print")
00774     int locked = 0;
00775     int i = 0;
00776 
00777     phTHIS_LOCK(locked);
00778 
00779     phPRINT("phPipeline {\n");
00780     for (i = 0; i < this->m_filterCount; i++ )
00781     {
00782         phPRINT("\t%s\n",
00783                 this->m_filterArray[i]->getName());
00784     }
00785     
00786     phPRINT("};\n");
00787     
00788     phTHIS_UNLOCK(locked);
00789 
00790     return phSUCCESS;
00791 error:
00792     phTHIS_ERROR_UNLOCK(locked);
00793 
00794     return phFAIL;
00795 }
00796 
00797 
00798 /* ---------------------------------------------------------------------- */
00799 int phPipeline::run()
00800 {
00801     phFUNCTION("phPipeline::run()")
00802 
00803     int             i_rc    = 0;
00804     int             w_rc    = 0;
00805     int             o_rc    = 0;
00806     unsigned int    i       = 0;
00807     phTimeInterval *runtime = new phTimeInterval("Pipeline Execution Time");
00808     phTimeStamp     elapsed;
00809     
00810     DEBUG_PRINT("Thread started\n");
00811 
00812     /* Check to see if the live source signal is set and reset it */
00813     rc = this->m_liveSourceSignal.tryTake();
00814     phPRINT_RC(rc,NULL,"this->m_liveSourceSignal.tryTake");
00815     
00816     if (this->m_liveSource != NULL)
00817     {
00818         rc = this->m_inputImage.connect(this->m_liveSource);
00819         phCHECK_RC(rc,NULL,"m_inputImage.connect()");
00820     }
00821     else if (this->m_inputImage.isConnected())
00822     {
00823         rc = this->m_inputImage.disconnect();
00824         phCHECK_RC(rc,NULL,"m_inputImage.disconnect()");
00825     }
00826 
00827     /* This input image is coming from outside of the phPipeline */
00828     rc = this->m_workspaceImage.connect(&this->m_inputImage);
00829     phCHECK_RC(rc,NULL,"m_workspaceImage.connect()");
00830     
00831     rc = this->signal_running();
00832     phPRINT_RC(rc,NULL,"this->signal_running");
00833 
00834     while (this->isRunning() && this->m_workspaceImage.isConnected())
00835     {
00836         rc = this->checkSignals();
00837         phPRINT_RC(rc,NULL,"this->checkSignals()");
00838         
00839         i_rc = phSUCCESS;
00840         if (this->m_inputImage.isConnected())
00841         {
00842             i_rc = this->m_inputImage.update();
00843             phPRINT_RC(i_rc,NULL,"this->m_inputImage.update failed.");
00844         }
00845         
00846         /*
00847         rc = m_workspaceImage.erase();
00848         phPRINT_RC(rc,NULL,"m_workspaceImage.erase failed.");
00849         */
00850         w_rc = this->m_workspaceImage.update();
00851         phPRINT_RC(w_rc,NULL,"this->m_workspaceImage.update failed.");
00852        
00853         /* Make sure o_rc is set to a default.
00854          * Don't use 'update' with m_originalImage cause it's a waste
00855          * of resources and a bit slower.
00856          * 'setImage' works better when one has knows everything 
00857          * will be sticking around. */
00858         o_rc = phSUCCESS;
00859         if (w_rc == phSUCCESS)
00860         {
00861             o_rc = this->m_originalImage.setImage(this->m_workspaceImage);
00862             phPRINT_RC(o_rc,NULL,"m_originalImage.setImage failed.");
00863         }
00864         if (this->isRunning() && 
00865             /* 0 means both of these got data, which is the
00866              * only way we're going to process the data */
00867             (i_rc == 0) && (w_rc == 0) && (o_rc == 0) && 
00868             (m_workspaceImage.isNull() == 0) && 
00869             (m_originalImage.isNull() == 0))
00870         {
00871             /* Get the timestamp for the start of the processing */
00872             if ((this->m_do_timing) && (this->m_filterCount > 0))
00873             {
00874                 runtime->start();
00875             }
00876 
00877             /* Start Processing Loop */
00878             for (i = 0; i < this->m_filterCount; i++ )
00879             {
00880                 this->m_filterArray[i]->process();
00881             }
00882             /* End Processing Loop */
00883             
00884             /* Get the timestamp for the end of the processing loop */
00885             if ((this->m_do_timing) && (this->m_filterCount > 0))
00886             {
00887                 runtime->stop();
00888                 
00889                 elapsed = runtime->elapsed();
00890 
00891                 rc = this->applyRuntime(elapsed);
00892                 phPRINT_RC(rc,NULL,"this->applyRuntime");
00893             }
00894 
00895             rc = this->m_outputImage.swapImage( this->m_workspaceImage );
00896             phPRINT_RC(rc,NULL,"m_outputImage.setImage");
00897         }
00898     }
00899 
00900     rc = this->m_workspaceImage.disconnect();
00901     phPRINT_RC(rc,NULL,"this->m_workspaceImage.disconnect() failed.");
00902     
00903     if (this->m_inputImage.isConnected())
00904     {
00905         rc = this->m_inputImage.disconnect();
00906         phCHECK_RC(rc,NULL,"m_inputImage.disconnect()");
00907     }
00908 
00909     phDelete(runtime);
00910     
00911     DEBUG_PRINT("Thread returning cleanly\n");
00912     
00913     return phSUCCESS;
00914 error:
00915     rc = this->m_workspaceImage.disconnect();
00916     phPRINT_RC(rc,NULL,"this->m_workspaceImage.disconnect() failed.");
00917     
00918     if (this->m_inputImage.isConnected())
00919     {
00920         rc = this->m_inputImage.disconnect();
00921         phPRINT_RC(rc,NULL,"m_inputImage.disconnect()");
00922     }
00923     
00924     phDelete(runtime);
00925     
00926     phPROGRESS("Thread returning with error\n");
00927 
00928     rc = this->signal_error();
00929     phPRINT_RC(rc,NULL,"this->signal_error");
00930     
00931     return phFAIL;
00932 }
00933 




Copyright (C) 2002 - 2007 Philip D.S. Thoren ( pthoren@users.sourceforge.net )
University Of Massachusetts at Lowell
Robotics Lab
SourceForge.net Logo

Generated on Sat Jun 16 02:44:02 2007 for phission by  doxygen 1.4.4