00001 /*!@file Transport/BufferedFrameIstream.H Frame-buffering layer on top of other FrameIstream objects */ 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/Transport/BufferedFrameIstream.H $ 00035 // $Id: BufferedFrameIstream.H 9547 2008-03-28 23:32:43Z rjpeters $ 00036 // 00037 00038 #ifndef TRANSPORT_BUFFEREDFRAMEISTREAM_H_DEFINED 00039 #define TRANSPORT_BUFFEREDFRAMEISTREAM_H_DEFINED 00040 00041 #include "Component/ModelParam.H" 00042 #include "Raster/GenericFrame.H" 00043 #include "Transport/FrameIstream.H" 00044 #include "Util/ErrorStrategy.H" 00045 #include "rutz/atomic.h" 00046 #include "rutz/circular_queue.h" 00047 00048 #include <list> 00049 00050 /// Puts a frame-buffering layer on top of any other FrameIstream object 00051 /** Frames are read from their source in a separate worker thread 00052 which fills a frame buffer queue; clients of this class running in 00053 the main thread can pull frames out of the queue. 00054 00055 To use this from the command-line with the standard --in option 00056 provided by InputFrameSeries, put "buf:" in front of your input 00057 spec, like this: --in=buf:frame#.pnm or --in=buf:foo.mpg. Then, 00058 the frames will actually be read in a worker thread that puts the 00059 frames in a FIFO queue; the main thread can retrieve frames from 00060 the queue. Control the number of frames in the queue with 00061 --input-buffer-size=N. To wait until the queue is completely 00062 filled before starting your main loop, put a startStream() just 00063 before the loop. 00064 */ 00065 class BufferedFrameIstream : public FrameIstream 00066 { 00067 public: 00068 BufferedFrameIstream(OptionManager& mgr); 00069 00070 virtual ~BufferedFrameIstream(); 00071 00072 /// Interpret the config string as a specification for our underlying input source 00073 virtual void setConfigInfo(const std::string& cfg); 00074 00075 /// Pass the frame number on to our underlying frame source 00076 virtual bool setFrameNumber(int n); 00077 00078 /// Get the specs of our frames 00079 virtual GenericFrameSpec peekFrameSpec(); 00080 00081 /// Returns the same frame time as our underlying source 00082 virtual SimTime getNaturalFrameTime() const; 00083 00084 /// Start filling our buffer 00085 virtual void startStream(); 00086 00087 /// Returns the next frame out of our buffer 00088 /** Returns an empty frame if either (1) the input source is 00089 exhausted, or (2) the input buffer underflowed prior to the 00090 input source being exhausted. It is up to the caller whether to 00091 treat premature underflow as a fatal error, or whether to retry 00092 after a delay. */ 00093 virtual GenericFrame readFrame(); 00094 00095 private: 00096 virtual void start2(); 00097 00098 virtual void stop1(); 00099 00100 static void* c_fill(void* p); 00101 00102 struct Checkpoint; 00103 00104 OModelParam<size_t> itsBufSize; 00105 00106 /// What to do in readFrame() if the buffer is empty due to underflow 00107 OModelParam<ErrorStrategy> itsUnderflowStrategy; 00108 00109 nub::soft_ref<FrameIstream> itsSrc; 00110 rutz::circular_queue<GenericFrame>* itsQ; 00111 pthread_mutex_t itsQmut; 00112 bool itsInputDone; 00113 bool itsStop; 00114 00115 pthread_t itsFillThread; 00116 00117 rutz::atomic_int_t itsNumFilled; 00118 00119 int itsMinNumFilled; 00120 00121 int itsInputFrameNum; 00122 int itsOutputFrameNum; 00123 00124 GenericFrameSpec itsFrameSpec; 00125 bool itsFrameSpecValid; 00126 00127 std::list<Checkpoint> itsCheckpoints; 00128 }; 00129 00130 // ###################################################################### 00131 /* So things look consistent in everyone's emacs... */ 00132 /* Local Variables: */ 00133 /* mode: c++ */ 00134 /* indent-tabs-mode: nil */ 00135 /* End: */ 00136 00137 #endif // TRANSPORT_BUFFEREDFRAMEISTREAM_H_DEFINED