00001 /*!@file Media/BufferedInputFrameSeries.C Buffered input with frames loaded in a worker thread */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00005 // by the University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Rob Peters <rjpeters at usc dot edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Media/BufferedInputFrameSeries.C $ 00035 // $Id: BufferedInputFrameSeries.C 9819 2008-06-17 05:48:53Z itti $ 00036 // 00037 00038 #ifndef MEDIA_BUFFEREDINPUTFRAMESERIES_C_DEFINED 00039 #define MEDIA_BUFFEREDINPUTFRAMESERIES_C_DEFINED 00040 00041 #include "Media/BufferedInputFrameSeries.H" 00042 00043 #include "Util/log.H" 00044 00045 struct BufferedInputFrameSeries::Checkpoint 00046 { 00047 Checkpoint(int f, int q, int mq) : framenum(f), qsize(q), minqsize(mq) {} 00048 00049 int framenum; 00050 int qsize; 00051 int minqsize; 00052 }; 00053 00054 // ###################################################################### 00055 BufferedInputFrameSeries:: 00056 BufferedInputFrameSeries(OptionManager& mgr, const size_t qsize, 00057 const bool forcergb) 00058 : 00059 ModelComponent(mgr, "Input Buffer", "BufferedInputFrameSeries"), 00060 itsSrc(new InputFrameSeries(mgr)), 00061 itsFrameSpec(), 00062 itsQ(qsize), 00063 itsInputDone(false), 00064 itsStop(false), 00065 itsNumFilled(), 00066 itsMinNumFilled(int(qsize)), 00067 itsFrameNum(0), 00068 itsCheckpoints(), 00069 itsForceRGB(forcergb) 00070 { 00071 if (0 != pthread_mutex_init(&itsQmut, NULL)) 00072 LFATAL("pthread_mutex_init() failed"); 00073 00074 this->addSubComponent(itsSrc); 00075 } 00076 00077 // ###################################################################### 00078 GenericFrameSpec BufferedInputFrameSeries::peekFrameSpec() const 00079 { 00080 if (!this->started()) 00081 LFATAL("must be start()-ed before peekFrameSpec()"); 00082 00083 return itsFrameSpec; 00084 } 00085 00086 // ###################################################################### 00087 GenericFrame BufferedInputFrameSeries::get(bool* did_underflow) 00088 { 00089 GenericFrame result; 00090 00091 const bool pop_ok = itsQ.pop_front(result); 00092 00093 if (pop_ok) 00094 { 00095 const int n = itsNumFilled.atomic_decr_return(); 00096 if (n < itsMinNumFilled) 00097 itsMinNumFilled = n; 00098 } 00099 00100 if (did_underflow != 0) 00101 // we have premature underflow if the pop fails (!pop_ok) before 00102 // our underlying input source is finished (!itsInputDone): 00103 *did_underflow = (!pop_ok && !itsInputDone); 00104 00105 if (++itsFrameNum % 100 == 0) 00106 itsCheckpoints.push_back 00107 (Checkpoint(itsFrameNum, itsNumFilled.atomic_get(), 00108 itsMinNumFilled)); 00109 00110 return result; 00111 } 00112 00113 // ###################################################################### 00114 void BufferedInputFrameSeries::start2() 00115 { 00116 itsFrameSpec = itsSrc->peekFrameSpec(); 00117 00118 if (0 != pthread_create(&itsFillThread, NULL, &c_fill, 00119 static_cast<void*>(this))) 00120 LFATAL("pthread_create() failed"); 00121 00122 itsMinNumFilled = int(itsQ.size()); 00123 itsFrameNum = 0; 00124 itsCheckpoints.clear(); 00125 } 00126 00127 // ###################################################################### 00128 void BufferedInputFrameSeries::stop1() 00129 { 00130 itsStop = true; 00131 00132 if (0 != pthread_join(itsFillThread, NULL)) 00133 LERROR("pthread_join() failed"); 00134 00135 for (std::list<Checkpoint>::const_iterator 00136 itr = itsCheckpoints.begin(), stop = itsCheckpoints.end(); 00137 itr != stop; ++itr) 00138 { 00139 LINFO("checkpoint frame %06d - queue fill : %d/%d (min %d)", 00140 (*itr).framenum, (*itr).qsize, int(itsQ.size()), 00141 (*itr).minqsize); 00142 } 00143 } 00144 00145 // ###################################################################### 00146 void* BufferedInputFrameSeries::c_fill(void* p) 00147 { 00148 try 00149 { 00150 BufferedInputFrameSeries* const b = 00151 static_cast<BufferedInputFrameSeries*>(p); 00152 00153 while (true) 00154 { 00155 if (b->itsStop) 00156 break; 00157 00158 // get the next frame: 00159 const FrameState is = b->itsSrc->updateNext(); 00160 if (is == FRAME_COMPLETE) 00161 { 00162 b->itsInputDone = true; 00163 return NULL; 00164 } 00165 00166 GenericFrame f = b->itsSrc->readFrame(); 00167 if (!f.initialized()) 00168 { 00169 b->itsInputDone = true; 00170 return NULL; 00171 } 00172 00173 // do we want to force the frame to have a native type of RGB? 00174 if (b->itsForceRGB) 00175 f = GenericFrame(f.asRgb()); 00176 00177 // now try to push it onto the queue (and just keep 00178 // re-trying if the push fails due to the queue being full): 00179 while (true) 00180 { 00181 if (b->itsStop) 00182 break; 00183 00184 if (b->itsQ.push_back(f) == true) 00185 { 00186 b->itsNumFilled.atomic_incr(); 00187 break; 00188 } 00189 00190 usleep(20000); 00191 } 00192 } 00193 } 00194 catch (...) 00195 { 00196 REPORT_CURRENT_EXCEPTION; 00197 exit(1); 00198 } 00199 00200 return NULL; 00201 } 00202 00203 // ###################################################################### 00204 /* So things look consistent in everyone's emacs... */ 00205 /* Local Variables: */ 00206 /* mode: c++ */ 00207 /* indent-tabs-mode: nil */ 00208 /* End: */ 00209 00210 #endif // MEDIA_BUFFEREDINPUTFRAMESERIES_C_DEFINED