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
00039 #include "Component/ModelManager.H"
00040 #include "Devices/FrameGrabberConfigurator.H"
00041 #include "Devices/DeviceOpts.H"
00042 #include "Image/DrawOps.H"
00043 #include "Image/Image.H"
00044 #include "Image/ShapeOps.H"
00045 #include "Image/CutPaste.H"
00046 #include "Image/ImageCache.H"
00047 #include "Image/Pixels.H"
00048 #include "GUI/SDLdisplay.H"
00049 #include "GUI/GUIOpts.H"
00050 #include "Raster/Raster.H"
00051 #include "Transport/FrameIstream.H"
00052 #include "Util/Timer.H"
00053 #include "Util/log.H"
00054 #include "Util/sformat.H"
00055 #include "Video/RgbConversion.H"
00056 #include "Raster/DeBayer.H"
00057
00058 #include <pthread.h>
00059
00060
00061 #define NAVG 20
00062
00063 #define MAXSAVETHREAD 4
00064
00065
00066 enum PreviewType
00067 {
00068 PrevAll,
00069 PrevTopLeft,
00070 PrevTopRight,
00071 PrevBotLeft,
00072 PrevBotRight,
00073 PrevCenter
00074 };
00075
00076
00077 uint fnb = 0;
00078 pthread_mutex_t qmutex_cache, qmutex_cacheRGB, qmutex_imaShow;
00079 pthread_mutex_t qmutex_mgz;
00080 ImageCache<byte> cache;
00081 ImageCache<PixRGB<byte> > cacheRGB;
00082 std::vector<std::string> base;
00083 bool saving = false;
00084 Image<PixRGB<byte> > imaShow;
00085 PreviewType prevType = PrevCenter;
00086 Dims showDim;
00087
00088
00089 static void* saveframes(void *)
00090 {
00091 while(1) {
00092 Image<PixRGB<byte> > imaRGB; bool havemore = false;
00093 uint cntTmp = 0;
00094
00095
00096 pthread_mutex_lock(&qmutex_cacheRGB);
00097 if (cacheRGB.size()){
00098 imaRGB = cacheRGB.pop_front();
00099 fnb++;
00100 cntTmp = fnb;
00101 }
00102 if (cacheRGB.size()) havemore = true;
00103 pthread_mutex_unlock(&qmutex_cacheRGB);
00104
00105
00106 if (imaRGB.initialized())
00107 {
00108
00109 const char *b = base[cntTmp % base.size()].c_str();
00110 Raster::WriteRGB(imaRGB, sformat("%s%06u.ppm", b, fnb));
00111 }
00112
00113 if (havemore == false) usleep(200);
00114 }
00115 return NULL;
00116 }
00117
00118
00119 static void* debayerframes(void *)
00120 {
00121 while(1){
00122 Image<byte> ima; bool havemore = false;
00123 Image<PixRGB<byte> > imaRGB;
00124
00125 pthread_mutex_lock(&qmutex_cache);
00126 if(cache.size()) ima = cache.pop_front();
00127 if(cache.size()) havemore = true;
00128 pthread_mutex_unlock(&qmutex_cache);
00129
00130 if( ima.initialized())
00131 {
00132 imaRGB = deBayer(ima, BAYER_GBRG);
00133 pthread_mutex_lock(&qmutex_imaShow);
00134
00135 switch(prevType){
00136 case PrevAll:
00137 imaShow = rescale(imaRGB, showDim.w(), showDim.h(),
00138 RESCALE_SIMPLE_NOINTERP);
00139 break;
00140 case PrevTopLeft:
00141 imaShow = crop(imaRGB, Point2D<int>(0,0), showDim);
00142 break;
00143 case PrevTopRight:
00144 imaShow = crop(imaRGB, Point2D<int>
00145 (imaRGB.getWidth()-showDim.w(),0), showDim);
00146 break;
00147 case PrevBotLeft:
00148 imaShow = crop(imaRGB, Point2D<int>
00149 (0,imaRGB.getHeight()-showDim.h()), showDim);
00150 break;
00151 case PrevBotRight:
00152 imaShow = crop(imaRGB, Point2D<int>
00153 (imaRGB.getWidth()-showDim.w(),
00154 imaRGB.getHeight()-showDim.h()), showDim);
00155 break;
00156 case PrevCenter:
00157 imaShow = crop(imaRGB, Point2D<int>
00158 ((imaRGB.getWidth()-showDim.w())/2,
00159 (imaRGB.getHeight()-showDim.h())/2),showDim);
00160 break;
00161 default:
00162 LFATAL("the preview type should between 0 and 5, now is %d", prevType);
00163 }
00164
00165 pthread_mutex_unlock(&qmutex_imaShow);
00166
00167 if(saving)
00168 {
00169 pthread_mutex_lock(&qmutex_cacheRGB);
00170 cacheRGB.push_back(imaRGB);
00171 pthread_mutex_unlock(&qmutex_cacheRGB);
00172 }
00173 }
00174
00175 if(havemore == false) usleep(20);
00176 }
00177 return NULL;
00178 }
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188 static int submain(const int argc, char** argv)
00189 {
00190
00191 ModelManager manager("Frame Grabber");
00192
00193
00194 nub::soft_ref<FrameGrabberConfigurator>
00195 gbc(new FrameGrabberConfigurator(manager));
00196 manager.addSubComponent(gbc);
00197
00198 nub::soft_ref<SDLdisplay> d(new SDLdisplay(manager));
00199 manager.addSubComponent(d);
00200
00201 manager.setOptionValString(&OPT_SDLdisplayPriority, "0");
00202 manager.setOptionValString(&OPT_FrameGrabberType, "XC");
00203 manager.setOptionValString(&OPT_SDLdisplayFullscreen,"false");
00204 manager.setOptionValString(&OPT_SDLdisplayDims, "960x640");
00205
00206
00207 if (manager.parseCommandLine(argc, argv, "<basename> ... <basename>",
00208 1, MAXSAVETHREAD) == false)
00209 return(1);
00210
00211
00212 nub::soft_ref<FrameIstream> gb = gbc->getFrameGrabber();
00213 if (gb.isInvalid())
00214 LFATAL("You need to have XC camera and XClibrary");
00215
00216
00217 for (uint i = 0; i < manager.numExtraArgs(); i ++)
00218 base.push_back(manager.getExtraArg(i));
00219
00220
00221 manager.start();
00222
00223
00224 Timer tim,timer; uint64 t[NAVG]; int frame = 0;
00225 d->clearScreen(PixRGB<byte>(128)); bool doit = true;
00226
00227 showDim = d->getDims();
00228 int iw = showDim.w(), ih = showDim.h();
00229 int dw = d->getDims().w(), dh = d->getDims().h();
00230
00231 int ovlyoff = (dw - iw) / 2 + dw * ((dh - ih) / 2);
00232 int ovluvoff = (dw - iw) / 4 + dw * ((dh - ih) / 8);
00233 int ystride = (dw - iw), uvstride = (dw - iw) / 2;
00234
00235 pthread_t saver[MAXSAVETHREAD];
00236 for(int ii = 0; ii<(int)base.size(); ii++)
00237 pthread_create(saver+ii, NULL, &saveframes, (void *)NULL);
00238
00239 pthread_t debayer1;
00240 pthread_create(&debayer1, NULL, &debayerframes, (void*) NULL);
00241
00242
00243 d->createYUVoverlay(SDL_YV12_OVERLAY);
00244
00245
00246 gb->startStream();
00247
00248
00249
00250
00251
00252 float frate = 0.0f;
00253 while(doit) {
00254 tim.reset();
00255
00256
00257 Image<byte> ima = gb->readGray();
00258 pthread_mutex_lock(&qmutex_cache);
00259 cache.push_back(ima);
00260 pthread_mutex_unlock(&qmutex_cache);
00261
00262
00263 uint64 t0 = tim.get();
00264
00265
00266 pthread_mutex_lock(&qmutex_imaShow);
00267 if (saving)
00268 {
00269 const std::string msg =
00270 sformat(" %.1ffps [%04d] ", frate, cacheRGB.size());
00271 writeText(imaShow, Point2D<int>(0, 0), msg.c_str());
00272 }
00273 else
00274 {
00275 const std::string msg =
00276 sformat(" [SPC] to save %.1ffp [%04d] ", frate, cacheRGB.size());
00277 writeText(imaShow, Point2D<int>(0, 0), msg.c_str());
00278 }
00279
00280
00281 SDL_Overlay* ovl = d->lockYUVoverlay();
00282 toVideoYUV422(imaShow, ovl->pixels[0] + ovlyoff,
00283 ovl->pixels[2] + ovluvoff,
00284 ovl->pixels[1] + ovluvoff,
00285 ystride, uvstride, uvstride);
00286
00287 d->unlockYUVoverlay();
00288 d->displayYUVoverlay(-1, SDLdisplay::NO_WAIT);
00289 pthread_mutex_unlock(&qmutex_imaShow);
00290
00291
00292
00293 int ii = (d->checkForKey());
00294 if(ii == ' ')
00295 { saving = ! saving;
00296 prevType = PrevAll;
00297 }
00298 else if(ii == 'q')
00299 prevType = PrevTopLeft;
00300 else if(ii == 'e')
00301 prevType = PrevTopRight;
00302 else if(ii == 'a')
00303 prevType = PrevBotLeft;
00304 else if(ii == 'd')
00305 prevType = PrevBotRight;
00306 else if(ii == 's')
00307 prevType = PrevCenter;
00308 else if(ii == 'w')
00309 prevType = PrevAll;
00310
00311 t[frame % NAVG] = tim.get();
00312 t0 = t[frame % NAVG] - t0;
00313 if (t0 > 20000ULL) LINFO("Display took %lluus", t0);
00314
00315
00316 if (frame % NAVG == 0 && frame > 0)
00317 {
00318 uint64 avg = 0ULL; for (int i = 0; i < NAVG; i ++) avg += t[i];
00319 frate = 1000.0F / float(avg) * float(NAVG);
00320 LINFO("Frame rate %f fps, buf size %u, time %f", frate,
00321 cacheRGB.size(), timer.getSecs());
00322 }
00323 frame ++;
00324 }
00325 d->destroyYUVoverlay();
00326 manager.stop();
00327
00328
00329 return 0;
00330 }
00331
00332 extern "C" int main(const int argc, char** argv)
00333 {
00334 try
00335 {
00336 return submain(argc, argv);
00337 }
00338 catch (...)
00339 {
00340 REPORT_CURRENT_EXCEPTION;
00341 }
00342
00343 return 1;
00344 }
00345
00346
00347
00348
00349
00350