00001 /*!@file Media/FrameRange.C A range of frames at a given inter-frame delay */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2003 // 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: Laurent Itti <itti@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Media/FrameRange.C $ 00035 // $Id: FrameRange.C 14376 2011-01-11 02:44:34Z pez $ 00036 // 00037 00038 #include "Media/FrameRange.H" 00039 00040 #include "Util/Assert.H" 00041 #include "Util/StringConversions.H" 00042 #include "Util/StringUtil.H" 00043 #include "Util/log.H" 00044 #include "Util/sformat.H" 00045 00046 #include <iterator> // for back_inserter() 00047 #include <limits> 00048 #include <vector> 00049 #include <cstdio> // for fopen() and friends 00050 00051 // ###################################################################### 00052 FrameRange::FrameRange() : 00053 itsFirst(0), 00054 itsStep(1), 00055 itsLast(0), 00056 itsDelayTimes(), 00057 itsEventTriggered(false) 00058 { 00059 // make sure there is always at least one element in the vector: 00060 itsDelayTimes.push_back(SimTime::ZERO()); 00061 } 00062 00063 FrameRange::FrameRange(int first, int step, int last, std::vector<SimTime> delays, bool eventTriggered) : 00064 itsFirst(first), 00065 itsStep(step), 00066 itsLast(last), 00067 itsDelayTimes(delays), 00068 itsEventTriggered(eventTriggered) 00069 { 00070 // make sure there is always at least one element in the vector: 00071 if(itsDelayTimes.size() == 0) 00072 { 00073 itsDelayTimes.push_back(SimTime::ZERO()); 00074 } 00075 } 00076 00077 // ###################################################################### 00078 std::string FrameRange::toString() const 00079 { 00080 const std::string range = 00081 itsStep == 1 00082 ? sformat("%d-%d", itsFirst, itsLast) 00083 : sformat("%d-%d-%d", itsFirst, itsStep, itsLast); 00084 00085 if (itsEventTriggered) 00086 { 00087 return sformat("%s@EVENT", range.c_str()); 00088 } 00089 else 00090 { 00091 ASSERT(itsDelayTimes.size() > 0); 00092 if (itsDelayTimes.size() == 1) 00093 { 00094 return sformat("%s@%.2fms", 00095 range.c_str(), itsDelayTimes[0].msecs()); 00096 } 00097 else 00098 { 00099 SimTime totstime = itsDelayTimes[0]; 00100 00101 for (size_t i = 1; i < itsDelayTimes.size(); ++i) 00102 totstime += itsDelayTimes[i] - itsDelayTimes[i-1]; 00103 00104 // average inter-frame delay: 00105 const double aifd = 00106 totstime.msecs() / double(itsDelayTimes.size()); 00107 return sformat("%s@variable delay " 00108 "(average inter-frame delay %.2fms)", 00109 range.c_str(), aifd); 00110 } 00111 } 00112 } 00113 00114 // ###################################################################### 00115 FrameRange FrameRange::fromString(const std::string& str) 00116 { 00117 const std::string::size_type at = str.find('@'); 00118 if (at == str.npos) 00119 conversion_error::raise<FrameRange> 00120 (str, "missing '@'; expected [first-[last]]@delay"); 00121 00122 const std::string range = str.substr(0, at); 00123 const std::string sdelay = str.substr(at+1, str.npos); 00124 00125 int xfirst = -2, xstep = -2, xlast = -2; 00126 00127 if (range.length() == 0) 00128 { 00129 xfirst = 0; 00130 xstep = 1; 00131 xlast = std::numeric_limits<int>::max(); 00132 } 00133 else 00134 { 00135 #define EXPECTED_FORMAT "expected [[first[-step]]-[last]]@delay" 00136 00137 std::vector<std::string> tokens; 00138 split(range, "-", std::back_inserter(tokens)); 00139 00140 if (tokens.size() != 2 && tokens.size() != 3) 00141 conversion_error::raise<FrameRange> 00142 (str, "missing '-'; " EXPECTED_FORMAT); 00143 00144 const std::string sfirst = tokens.front(); 00145 const std::string slast = tokens.back(); 00146 00147 if (sfirst.length() == 0) 00148 xfirst = 0; 00149 else if (sscanf(sfirst.c_str(), "%d", &xfirst) != 1) 00150 conversion_error::raise<FrameRange> 00151 (str, "bogus 'first'; " EXPECTED_FORMAT); 00152 00153 if (slast.length() == 0 00154 || slast.compare("MAX") == 0 00155 || slast.compare("max") == 0) 00156 { 00157 xlast = std::numeric_limits<int>::max(); 00158 } 00159 else if (sscanf(slast.c_str(), "%d", &xlast) != 1) 00160 { 00161 conversion_error::raise<FrameRange> 00162 (str, "bogus 'last'; " EXPECTED_FORMAT); 00163 } 00164 00165 if (tokens.size() == 3) 00166 { 00167 if (sscanf(tokens[1].c_str(), "%d", &xstep) != 1) 00168 conversion_error::raise<FrameRange> 00169 (str, "bogus 'step'; " EXPECTED_FORMAT); 00170 00171 if (xstep <= 0) 00172 conversion_error::raise<FrameRange> 00173 (str, "bogus 'step'; must be strictly greater than zero"); 00174 } 00175 else 00176 xstep = 1; 00177 } 00178 00179 FrameRange result; 00180 00181 result.itsFirst = xfirst; 00182 result.itsStep = xstep; 00183 result.itsLast = xlast; 00184 result.itsEventTriggered = false; 00185 result.itsDelayTimes.resize(0); 00186 00187 LDEBUG("sdelay: %s", sdelay.c_str()); 00188 00189 // check for magic values of sdelay: 00190 if (sdelay.compare("EVENT") == 0) { 00191 result.itsEventTriggered = true; 00192 // make sure there is always at least one element in the vector: 00193 result.itsDelayTimes.push_back(SimTime::ZERO()); 00194 } else { 00195 // ok, sdelay didn't have a magic value 00196 // check if it's a filename 00197 const std::string::size_type suffix_pos = sdelay.find(".fl"); 00198 if (suffix_pos == str.npos) { 00199 // no suffix, so assume sdelay is a time string 00200 // pass "ms" to indicate that the default units are milliseconds 00201 LDEBUG("didn't find fl suffix"); 00202 result.itsDelayTimes.push_back(SimTime::fromString(sdelay, "ms")); 00203 } else { 00204 // the delay should be a .fl filename (necessary to account for variable framerates) 00205 // the expected format of .fl files is defined in the help message of OPT_InputFrameRange (FrameSeries.C) 00206 LDEBUG("found fl suffix"); 00207 std::string fl_filename=sdelay; 00208 FILE *fl = fopen(fl_filename.c_str(), "r"); 00209 if (fl == NULL) LFATAL("Cannot open %s", fl_filename.c_str()); 00210 // double prevstime; // previous simulation time 00211 double nextstime; // next simulation time 00212 int i=1; // index of lines in fl file 00213 if (fscanf(fl, "%*s %lf\n", &nextstime) != 1) // read first line 00214 { 00215 fclose(fl); 00216 LFATAL("Error reading from %s[%i]", 00217 fl_filename.c_str(), i); 00218 } 00219 if (nextstime!=0) 00220 { 00221 fclose(fl); 00222 LFATAL("Simulation start time must be 0, " 00223 "but is %.2f in file: %s[%d]", 00224 nextstime, fl_filename.c_str(), i); 00225 } 00226 while (!feof(fl)) { 00227 i++; 00228 //prevstime=nextstime; 00229 if (fscanf(fl, "%*s %lf\n", &nextstime) != 1) 00230 { 00231 fclose(fl); 00232 LFATAL("Error reading from %s[%d]", 00233 fl_filename.c_str(), i); 00234 } 00235 result.itsDelayTimes.push_back(SimTime::MSECS(nextstime)); 00236 } 00237 } 00238 LDEBUG("added %"ZU" delays to itsDelayTimes", result.itsDelayTimes.size()); 00239 } 00240 00241 LDEBUG("parsed FrameRange string '%s' as '%s'", 00242 str.c_str(), result.toString().c_str()); 00243 00244 return result; 00245 } 00246 00247 // ###################################################################### 00248 bool FrameRange::operator==(const FrameRange& that) const 00249 { 00250 return (this->itsFirst == that.itsFirst 00251 && this->itsStep == that.itsStep 00252 && this->itsLast == that.itsLast 00253 && this->itsDelayTimes == that.itsDelayTimes 00254 && this->itsEventTriggered == that.itsEventTriggered); 00255 } 00256 00257 00258 // ###################################################################### 00259 /* So things look consistent in everyone's emacs... */ 00260 /* Local Variables: */ 00261 /* indent-tabs-mode: nil */ 00262 /* End: */