psycho-movie-fixicon2.C
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 #include "Component/ModelManager.H"
00038 #include "Image/Image.H"
00039 #include "Raster/Raster.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
00055 #define CACHELEN 150
00056
00057
00058 static bool cacheFrame(nub::soft_ref<InputMPEGStream>& mp,
00059 std::deque<VideoFrame>& cache)
00060 {
00061 const VideoFrame frame = mp->readVideoFrame();
00062 if (!frame.initialized()) return false;
00063
00064 cache.push_front(frame);
00065 return true;
00066 }
00067
00068
00069 static int submain(const int argc, char** argv)
00070 {
00071 MYLOGVERB = LOG_INFO;
00072
00073
00074 ModelManager manager("Psycho Movie");
00075
00076
00077 nub::soft_ref<InputMPEGStream> mp
00078 (new InputMPEGStream(manager, "Input MPEG Stream", "InputMPEGStream"));
00079 manager.addSubComponent(mp);
00080
00081 nub::soft_ref<EventLog> el(new EventLog(manager));
00082 manager.addSubComponent(el);
00083
00084 nub::soft_ref<EyeTrackerConfigurator>
00085 etc(new EyeTrackerConfigurator(manager));
00086 manager.addSubComponent(etc);
00087
00088 nub::soft_ref<PsychoDisplay> d(new PsychoDisplay(manager));
00089 manager.addSubComponent(d);
00090
00091 manager.setOptionValString(&OPT_InputMPEGStreamPreload, "true");
00092 manager.setOptionValString(&OPT_EventLogFileName, "psychodata.psy");
00093 manager.setOptionValString(&OPT_EyeTrackerType, "ISCAN");
00094
00095
00096 if (manager.parseCommandLine(argc, argv,
00097 "<movie1.mpg> ... <movieN.mpg>", 1, -1)==false)
00098 return(1);
00099
00100
00101 nub::soft_ref<EyeTracker> et = etc->getET();
00102 d->setEyeTracker(et);
00103 d->setEventLog(el);
00104 et->setEventLog(el);
00105
00106
00107 if (etc->getModelParamString("EyeTrackerType").compare("EL") == 0)
00108 d->setModelParamVal("SDLslaveMode", true);
00109
00110
00111 manager.start();
00112
00113
00114 LINFO("*****************************************************************************");
00115 LINFO("visual acuity test: [r] to regenerate another string; other keys to continue.");
00116 int key;
00117 do {
00118 d->displayRandomText(7, 6);
00119 key = d->waitForKey(true);
00120 } while(key == 114 || key == 101 || key == 116 || key == 102);
00121
00122
00123 d->pushEventBegin("Calibration");
00124 et->calibrate(d);
00125 d->pushEventEnd("Calibration");
00126
00127
00128 Image< PixRGB<byte> > fixicon =
00129 Raster::ReadRGB(d->getModelParamString("PsychoDisplayFixationIcon"));
00130
00131
00132 if (etc->getModelParamString("EyeTrackerType").compare("EL") == 0){
00133 et->closeSDL();
00134 d->openDisplay();
00135 LINFO("Switching SDL: Eyelink-->iLab");
00136 }else{
00137 d->clearScreen();
00138 }
00139
00140 LINFO("Press any key to start......");
00141 d->displayText("Press any key to start......");
00142 d->waitForKey(true);
00143
00144
00145 uint nbmovies = manager.numExtraArgs();
00146 uint nbmovses = 5;
00147 int index[nbmovies], sindex[nbmovses];
00148
00149
00150 LINFO("Randomizing movies...");
00151 int iidx = 0;
00152 for (uint i=0; i<nbmovies; i++) {
00153 sindex[i%nbmovses] = i;
00154 if (i%nbmovses == nbmovses-1){
00155 randShuffle(sindex, nbmovses);
00156 for (uint j=0; j<nbmovses; j++) {
00157 index[iidx] = sindex[j];
00158 iidx++;
00159 }
00160 }
00161 }
00162
00163
00164 int x, y, w, h;
00165 for (uint i = 0; i < nbmovies; i ++)
00166 {
00167
00168 d->clearScreen();
00169 bool streaming = true;
00170 LINFO("Buffering '%s'...", manager.getExtraArg(index[i]).c_str());
00171 mp->setFileName(manager.getExtraArg(index[i]));
00172
00173
00174 w = mp->getWidth();
00175 h = mp->getHeight();
00176 x = (d->getWidth()-w)/2;
00177 y = (d->getHeight()-h)/2;
00178
00179 std::deque<VideoFrame> cache;
00180 for (uint j = 0; j < CACHELEN; j ++)
00181 {
00182 streaming = cacheFrame(mp, cache);
00183 if (streaming == false) break;
00184 }
00185 LINFO("'%s' ready.", manager.getExtraArg(index[i]).c_str());
00186 LINFO("Video loaded (%i/%i). Press [Space] to continue, or [ESC] to quit the program.", i+1, nbmovies);
00187
00188
00189 sleep(1); if (system("/bin/sync")) LERROR("error in sync");
00190
00191
00192 d->displayFixationIcon(fixicon);
00193
00194
00195 d->waitForKey(true); int frame = 0;
00196 d->waitNextRequestedVsync(false, true);
00197 d->pushEvent(std::string("===== Playing movie: ") +
00198 manager.getExtraArg(index[i]) + " =====");
00199
00200
00201 et->track(true);
00202
00203
00204 d->displayFixationIconBlink(fixicon);
00205
00206
00207 d->createVideoOverlay(VIDFMT_YUV420P,mp->getWidth(),mp->getHeight());
00208
00209
00210 rutz::time start = rutz::time::wall_clock_now();
00211 while(cache.size())
00212 {
00213
00214 if (streaming) streaming = cacheFrame(mp, cache);
00215
00216
00217 VideoFrame vidframe = cache.back();
00218 d->displayVideoOverlay_pos(vidframe, frame,
00219 SDLdisplay::NEXT_VSYNC,
00220 x, y, w, h);
00221 cache.pop_back();
00222
00223 ++frame;
00224 }
00225 rutz::time stop = rutz::time::wall_clock_now();
00226 const double secs = (stop-start).sec();
00227 LINFO("%d frames in %.04f sec (~%.04f fps)", frame, secs, frame/secs);
00228
00229
00230
00231
00232
00233 d->destroyYUVoverlay();
00234 d->clearScreen();
00235
00236
00237 usleep(50000);
00238 et->track(false);
00239
00240
00241 if (i<nbmovies-1){
00242 if (etc->getModelParamString("EyeTrackerType").compare("EL") == 0){
00243 d->closeDisplay();
00244 et->openSDL();
00245 if ((i+1)%5 == 0){
00246
00247 d->clearScreen();
00248 d->displayText("Please Take a Break");
00249 LINFO("Break time. Press [Space] to continue, or [ESC] to terminate the experiment.");
00250 d->waitForKey(true);
00251 d->displayText("Calibration");
00252 d->pushEventBegin("Calibration");
00253 et->calibrate(d);
00254 d->pushEventEnd("Calibration");
00255 }else{
00256 LINFO("Drift Correction. Press [Space] to continue, or [ESC] to calibrate.");
00257 et->recalibrate(d,13);
00258 }
00259 LINFO("Switching SDL for Calibration ");
00260 }else{
00261
00262 et->recalibrate(d,13);
00263 }
00264 }
00265 }
00266
00267 d->clearScreen();
00268 d->displayText("Experiment complete. Thank you!");
00269 d->waitForKey(true);
00270
00271
00272 manager.stop();
00273
00274
00275 return 0;
00276 }
00277
00278
00279 extern "C" int main(const int argc, char** argv)
00280 {
00281
00282
00283
00284
00285 try
00286 {
00287 return submain(argc, argv);
00288 }
00289 catch (...)
00290 {
00291 REPORT_CURRENT_EXCEPTION;
00292 }
00293
00294 return 1;
00295 }
00296
00297
00298
00299
00300
00301