videograb.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
00038 #include "Component/ModelManager.H"
00039 #include "Devices/FrameGrabberConfigurator.H"
00040 #include "Image/DrawOps.H"
00041 #include "Image/Image.H"
00042 #include "Image/Image.H"
00043 #include "Image/ImageCache.H"
00044 #include "Image/Pixels.H"
00045 #include "GUI/SDLdisplay.H"
00046 #include "GUI/GUIOpts.H"
00047 #include "Raster/Raster.H"
00048 #include "Transport/FrameIstream.H"
00049 #include "Util/Timer.H"
00050 #include "Util/log.H"
00051 #include "Util/sformat.H"
00052 #include "Video/RgbConversion.H"
00053
00054 #include <pthread.h>
00055
00056
00057 #define NAVG 20
00058
00059
00060 #define MAXQLEN 1000
00061
00062 pthread_mutex_t qmutex;
00063 ImageCache< PixRGB<byte> > cache;
00064 std::vector<std::string> base;
00065
00066 static void* saveframes(void *)
00067 {
00068 uint fnb = 0;
00069 while(1) {
00070 Image< PixRGB<byte> > ima; bool havemore = false;
00071
00072
00073 pthread_mutex_lock(&qmutex);
00074 if (cache.size()) ima = cache.pop_front();
00075 if (cache.size()) havemore = true;
00076 pthread_mutex_unlock(&qmutex);
00077
00078
00079 if (ima.initialized())
00080 {
00081
00082 const char *b = base[fnb % base.size()].c_str();
00083 Raster::WriteRGB(ima, sformat("%s%06u.ppm", b, fnb++));
00084 }
00085
00086 if (havemore == false) usleep(1000);
00087 }
00088 return NULL;
00089 }
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 static int submain(const int argc, char** argv)
00101 {
00102
00103 ModelManager manager("Frame Grabber");
00104
00105
00106 nub::soft_ref<FrameGrabberConfigurator>
00107 gbc(new FrameGrabberConfigurator(manager));
00108 manager.addSubComponent(gbc);
00109
00110 nub::soft_ref<SDLdisplay> d(new SDLdisplay(manager));
00111 manager.addSubComponent(d);
00112
00113 manager.setOptionValString(&OPT_SDLdisplayPriority, "0");
00114
00115
00116 if (manager.parseCommandLine(argc, argv, "<basename> ... <basename>",
00117 1, -1) == false)
00118 return(1);
00119
00120
00121 nub::soft_ref<FrameIstream> gb = gbc->getFrameGrabber();
00122 if (gb.isInvalid())
00123 LFATAL("You need to select a frame grabber type via the "
00124 "--fg-type=XX command-line option for this program "
00125 "to be useful");
00126
00127
00128 for (uint i = 0; i < manager.numExtraArgs(); i ++)
00129 base.push_back(manager.getExtraArg(i));
00130
00131
00132 manager.start();
00133
00134
00135 Timer tim; uint64 t[NAVG]; int frame = 0;
00136 d->clearScreen(PixRGB<byte>(128)); bool doit = true;
00137
00138 int iw = gb->getWidth(), ih = gb->getHeight();
00139 int dw = d->getDims().w(), dh = d->getDims().h();
00140 if (iw > dw || ih > dh)
00141 {
00142 LERROR("Grab frame size must be smaller than display size");
00143 doit = false;
00144 }
00145
00146 int ovlyoff = (dw - iw) / 2 + dw * ((dh - ih) / 2);
00147 int ovluvoff = (dw - iw) / 4 + dw * ((dh - ih) / 8);
00148 int ystride = (dw - iw), uvstride = (dw - iw) / 2;
00149 bool saving = false; float frate = 0.0f;
00150 pthread_t saver;
00151 pthread_create(&saver, NULL, &saveframes, (void *)NULL);
00152
00153
00154 d->createYUVoverlay(SDL_YV12_OVERLAY);
00155
00156
00157 gb->startStream();
00158
00159
00160 while(doit) {
00161 tim.reset();
00162
00163
00164 Image< PixRGB<byte> > ima = gb->readRGB();
00165
00166
00167 uint64 t0 = tim.get();
00168
00169
00170 if (saving)
00171 {
00172 pthread_mutex_lock(&qmutex);
00173 cache.push_back(ima);
00174 pthread_mutex_unlock(&qmutex);
00175 const std::string msg = sformat(" %.1ffps [%04d] ", frate, cache.size());
00176 writeText(ima, Point2D<int>(0, 0), msg.c_str(), PixRGB<byte>(255), PixRGB<byte>(0));
00177 }
00178 else
00179 {
00180 const std::string msg = sformat(" [SPC] to save [%04d] ", cache.size());
00181 writeText(ima, Point2D<int>(0, 0), msg.c_str(), PixRGB<byte>(255), PixRGB<byte>(0));
00182 }
00183
00184
00185 SDL_Overlay* ovl = d->lockYUVoverlay();
00186 toVideoYUV422(ima, ovl->pixels[0] + ovlyoff,
00187 ovl->pixels[2] + ovluvoff,
00188 ovl->pixels[1] + ovluvoff,
00189 ystride, uvstride, uvstride);
00190 d->unlockYUVoverlay();
00191 d->displayYUVoverlay(-1, SDLdisplay::NO_WAIT);
00192
00193
00194
00195 if (d->checkForKey() == ' ') saving = ! saving;
00196
00197 t[frame % NAVG] = tim.get();
00198 t0 = t[frame % NAVG] - t0;
00199 if (t0 > 20000ULL) LINFO("Display took %lluus", t0);
00200
00201
00202 if (frame % NAVG == 0 && frame > 0)
00203 {
00204 uint64 avg = 0ULL; for (int i = 0; i < NAVG; i ++) avg += t[i];
00205 frate = 1000.0F / float(avg) * float(NAVG);
00206 }
00207 frame ++;
00208 }
00209
00210
00211 d->destroyYUVoverlay();
00212 manager.stop();
00213
00214
00215 return 0;
00216 }
00217
00218 extern "C" int main(const int argc, char** argv)
00219 {
00220 try
00221 {
00222 return submain(argc, argv);
00223 }
00224 catch (...)
00225 {
00226 REPORT_CURRENT_EXCEPTION;
00227 }
00228
00229 return 1;
00230 }
00231
00232
00233
00234
00235
00236