00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "Component/ModelManager.H"
00039 #include "Image/Image.H"
00040 #include "Media/MPEGStream.H"
00041 #include "Media/MediaOpts.H"
00042 #include "Psycho/PsychoDisplay.H"
00043 #include "Psycho/EyeTrackerConfigurator.H"
00044 #include "Psycho/EyeTracker.H"
00045 #include "Psycho/PsychoOpts.H"
00046 #include "Component/EventLog.H"
00047 #include "Component/ComponentOpts.H"
00048 #include "Util/MathFunctions.H"
00049 #include "Util/Types.H"
00050 #include "Video/VideoFrame.H"
00051 #include "rutz/time.h"
00052
00053 #include <deque>
00054 #include <string>
00055 #include <fstream>
00056 #include <vector>
00057 #include <iostream>
00058 #include <algorithm>
00059 #include <assert.h>
00060
00061 #define CACHELEN 150
00062
00063
00064 static bool cacheFrame(nub::soft_ref<InputMPEGStream>& mp,
00065 std::deque<VideoFrame>& cache)
00066 {
00067 const VideoFrame frame = mp->readVideoFrame();
00068 if (!frame.initialized()) return false;
00069
00070 cache.push_front(frame);
00071 return true;
00072 }
00073
00074
00075 void Tokenize(const std::string& str,
00076 std::vector<std::string>& tokens,
00077 const std::string& delimiters = " ")
00078 {
00079 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
00080 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
00081 while (std::string::npos != pos || std::string::npos != lastPos)
00082 {
00083 tokens.push_back(str.substr(lastPos, pos - lastPos));
00084 lastPos = str.find_first_not_of(delimiters, pos);
00085 pos = str.find_first_of(delimiters, lastPos);
00086 }
00087 }
00088
00089
00090 static int submain(const int argc, char** argv)
00091 {
00092 MYLOGVERB = LOG_INFO;
00093
00094
00095 ModelManager manager("Psycho Movie");
00096
00097
00098 nub::soft_ref<InputMPEGStream> mp
00099 (new InputMPEGStream(manager, "Input MPEG Stream", "InputMPEGStream"));
00100 manager.addSubComponent(mp);
00101
00102 nub::soft_ref<EventLog> el(new EventLog(manager));
00103 manager.addSubComponent(el);
00104
00105 nub::soft_ref<EyeTrackerConfigurator>
00106 etc(new EyeTrackerConfigurator(manager));
00107 manager.addSubComponent(etc);
00108
00109 nub::soft_ref<PsychoDisplay> d(new PsychoDisplay(manager));
00110 manager.addSubComponent(d);
00111
00112 manager.setOptionValString(&OPT_InputMPEGStreamPreload, "true");
00113 manager.setOptionValString(&OPT_EventLogFileName, "psychodata.psy");
00114 manager.setOptionValString(&OPT_EyeTrackerType, "ISCAN");
00115
00116
00117 if (manager.parseCommandLine(argc, argv,
00118 "<display_loc.txt> <movie1.mpg> ... <movieN.mpg>", 2, -1)==false)
00119 return(1);
00120
00121
00122 nub::soft_ref<EyeTracker> et = etc->getET();
00123 d->setEyeTracker(et);
00124 d->setEventLog(el);
00125 et->setEventLog(el);
00126
00127
00128 if (etc->getModelParamString("EyeTrackerType").compare("EL") == 0)
00129 d->setModelParamVal("SDLslaveMode", true);
00130
00131
00132 manager.start();
00133
00134
00135 const char * display_loc = manager.getExtraArg(0).c_str();
00136 std::ifstream in( display_loc );
00137
00138 if (! in) {
00139 LINFO("error: unable to open display_loc file: %s", display_loc);
00140 return -1;
00141 }
00142
00143 std::vector< std::vector<std::string> > cdl;
00144 std::string line;
00145 while( !getline(in, line).eof()){
00146 std::vector<std::string> tokens;
00147 Tokenize(line, tokens);
00148 cdl.push_back(tokens);
00149 }
00150 in.close();
00151
00152
00153 uint nbmovies = manager.numExtraArgs()-1;
00154 int index[nbmovies];
00155 for (uint i = 0; i < nbmovies; i ++) index[i] = i;
00156 LINFO("Randomizing movies..."); randShuffle(index,nbmovies);
00157
00158
00159 et->calibrate(d);
00160
00161 if (etc->getModelParamString("EyeTrackerType").compare("EL") == 0){
00162 et->closeSDL();
00163 d->openDisplay();
00164 LINFO("Switching SDL: EyeLink-->iLab");
00165 }else{
00166 d->clearScreen();
00167 }
00168
00169 d->displayText("<SPACE> to start watching movies");
00170 d->waitForKey();
00171
00172
00173 PixRGB<byte> ori_bgcolor = d->getGrey();
00174 PixRGB<byte> black_bgcolor = PixRGB<byte>(0,0,0);
00175
00176
00177 for (uint i = 0; i < nbmovies; i ++)
00178 {
00179
00180 int x = 100, y = 100, w = 1280, h = 1024;
00181 int sw = d->getWidth(), sh = d->getHeight();
00182 std::string playmovie = manager.getExtraArg(index[i]+1).c_str();
00183 std::vector< std::vector<std::string> >::iterator iter_ii;
00184 std::vector<std::string>::iterator iter_jj;
00185 std::string loc = "default";
00186 for(iter_ii=cdl.begin(); iter_ii!=cdl.end(); iter_ii++)
00187 {
00188 iter_jj = (*iter_ii).begin();
00189 if(playmovie.find(*iter_jj, 0) != std::string::npos){
00190 iter_jj++;
00191 loc = *iter_jj;
00192 if(loc.compare("0") == 0){
00193 x = sw/2 - w/2;
00194 y = sh/2 - h/2;
00195 }else if(loc.compare("1") == 0){
00196 x = sw - w; y = 0;
00197 }else if(loc.compare("2") == 0){
00198 x = 0; y = 0;
00199 }else if(loc.compare("3") == 0){
00200 x = sw - w; y = sh - h;
00201 }else if(loc.compare("4") == 0){
00202 x = 0; y = sh - h;
00203 }else{
00204 x = sw/2 - w/2;
00205 y = sh/2 - h/2;
00206 }
00207 }
00208 }
00209
00210 d->changeBackgroundColor(black_bgcolor);
00211
00212 d->clearScreen();
00213 bool streaming = true;
00214 LINFO("Buffering '%s'...", manager.getExtraArg(index[i]+1).c_str());
00215 mp->setFileName(manager.getExtraArg(index[i]+1));
00216
00217 std::deque<VideoFrame> cache;
00218 for (uint j = 0; j < CACHELEN; j ++)
00219 {
00220 streaming = cacheFrame(mp, cache);
00221 if (streaming == false) break;
00222 }
00223 LINFO("'%s' ready.", manager.getExtraArg(index[i]).c_str());
00224
00225
00226 sleep(1); if (system("/bin/sync")) LERROR("error in sync");
00227
00228
00229 d->displayRedDotFixation();
00230
00231
00232 d->waitForKey(); int frame = 0;
00233 d->waitNextRequestedVsync(false, true);
00234 d->pushEvent(std::string("===== Playing movie: ") +
00235 manager.getExtraArg(index[i]+1) + " =====");
00236 d->pushEvent(std::string("movie is displayed at location: ") + loc);
00237
00238
00239 et->track(true);
00240
00241
00242 d->clearScreen();
00243 d->displayRedDotFixationBlink(x+w/2, y+h/2);
00244
00245
00246 d->createVideoOverlay(VIDFMT_YUV420P, mp->getWidth(), mp->getHeight());
00247
00248
00249 d->changeBackgroundColor(PixRGB<byte>(0,0,0));
00250 rutz::time start = rutz::time::wall_clock_now();
00251 while(cache.size())
00252 {
00253
00254 if (streaming) streaming = cacheFrame(mp, cache);
00255
00256
00257 VideoFrame vidframe = cache.back();
00258 d->displayVideoOverlay_pos(vidframe, frame,
00259 SDLdisplay::NEXT_VSYNC,
00260 x, y, w, h);
00261 cache.pop_back();
00262
00263 ++frame;
00264 }
00265 rutz::time stop = rutz::time::wall_clock_now();
00266 const double secs = (stop-start).sec();
00267 LINFO("%d frames in %.02f sec (~%.02f fps)", frame, secs, frame/secs);
00268
00269
00270
00271
00272
00273 d->destroyYUVoverlay();
00274 d->clearScreen();
00275
00276
00277 usleep(50000);
00278 et->track(false);
00279
00280 if(i%10 == 0 && i> 0 && i<nbmovies-1) {
00281
00282 d->changeBackgroundColor(ori_bgcolor);
00283 d->displayText("Please take a break, press <SPACE> to continue");
00284 d->waitForKey();
00285
00286 if (etc->getModelParamString("EyeTrackerType").compare("EL") == 0){
00287 d->closeDisplay();
00288 et->openSDL();
00289 et->calibrate(d);
00290 et->closeSDL();
00291 d->openDisplay();
00292 LINFO("Switching SDL for quick calibration");
00293 }else{
00294 d->clearScreen();
00295 d->displayISCANcalib();
00296 d->waitForKey();
00297
00298 d->displayText("<SPACE> for eye-tracker calibration");
00299 d->waitForKey();
00300 d->displayEyeTrackerCalibration(3, 3);
00301 d->clearScreen();
00302 }
00303
00304 d->displayText("<SPACE> to start watching movies");
00305 d->waitForKey();
00306 d->changeBackgroundColor(black_bgcolor);
00307 }
00308 }
00309
00310 d->changeBackgroundColor(ori_bgcolor);
00311 d->clearScreen();
00312 d->displayText("Experiment complete. Thank you!");
00313 d->waitForKey();
00314
00315
00316 manager.stop();
00317
00318
00319 return 0;
00320 }
00321
00322
00323 extern "C" int main(const int argc, char** argv)
00324 {
00325
00326
00327
00328
00329 try
00330 {
00331 return submain(argc, argv);
00332 }
00333 catch (...)
00334 {
00335 REPORT_CURRENT_EXCEPTION;
00336 }
00337
00338 return 1;
00339 }
00340
00341
00342
00343
00344
00345