getVideoExample.cpp

This example client requests video images from the server and saves them repeatedly to a file named "video.jpg", or to a series of files ("video1.jpg", "video2.jpg", etc.) if you give the -counter option. Give the image request rate in images per second with the -rate option (or use -1 to let the server decide when to send image; may not work with all servers).

Connect to SAVserver, ACTS, or another video server to get images.

To make a movie from the images, you can use ffmpeg on Linux. First run with frame rate and counter options to save multiple images: ./getVideoExample -host robothost -port 7272 -rate 20 -counter Then use ffmpeg: ffmpeg -i videod.jpeg -r 20 movie.mpeg See ffmpeg -h for full list of options.

00001 #include "Aria.h"
00002 #include "ArNetworking.h"
00003 
00025 bool useCounter = false;
00026 unsigned long counter = 1;
00027 
00028 double rate = 0;
00029 int rateAsTime = 0;
00030 
00031 void jpegHandler(ArNetPacket *packet)
00032 {
00033   unsigned int width;
00034   unsigned int height;
00035   static unsigned char jpeg[50000];
00036   int jpegSize;
00037   FILE *file;
00038 
00039   width = packet->bufToUByte2();
00040   height = packet->bufToUByte2();
00041   jpegSize = packet->getDataLength() - packet->getDataReadLength();
00042   if(jpegSize > 50000)
00043   {
00044     ArLog::log(ArLog::Normal, "Cannot save image, it's too big. (image is %d bytes, my buffer is 50000 bytes)", jpegSize);
00045     return;
00046   }
00047   packet->bufToData((char *)jpeg, jpegSize);
00048   char filename[128];
00049   char tmpFilename[128];
00050   sprintf(tmpFilename, "tmp.jpg");
00051   if ((file = ArUtil::fopen(tmpFilename, "wb")) != NULL)
00052   {
00053     fwrite(jpeg, jpegSize, 1, file);
00054     fclose(file);
00055     if(useCounter)
00056       snprintf(filename, 64, "video%lu.jpg", counter++);
00057     else
00058       strcpy(filename, "video.jpg");
00059 #ifdef WIN32
00060     // On windows, rename() fails if the new file already exists
00061     unlink(filename);
00062 #endif
00063     if (rename(tmpFilename, filename) == 0)
00064       ArLog::log(ArLog::Normal, "Wrote a %dx%d image, %d bytes, named %s.", width, height, jpegSize, filename);
00065     else
00066       ArLog::log(ArLog::Normal, "Wrote a %dx%d image, %d bytes, named %s (could not rename to real name).", width, height, jpegSize, tmpFilename);
00067   }
00068   else
00069     ArLog::log(ArLog::Normal, "Could not write temp file %s", tmpFilename);
00070 
00071   if (rate == 0 || rateAsTime == 0)
00072   {
00073     ArLog::log(ArLog::Normal, "Only one frame was requested, so exiting");
00074     Aria::exit(0);
00075   }
00076 }
00077 
00078 int main(int argc, char **argv)
00079 {
00080 
00081 #ifndef WIN32
00082   ArDaemonizer daemonizer(&argc, argv);
00083   bool isDaemonized = false;
00084   if (!daemonizer.daemonize())
00085   {
00086     ArLog::log(ArLog::Terse, "Could not daemonize process");
00087     exit(1);
00088   }
00089   if (daemonizer.isDaemonized())
00090     isDaemonized = true;
00091 #endif
00092 
00093   Aria::init();
00094   ArLog::init(ArLog::File, ArLog::Normal, "getVideoLog.txt", true, true, true);
00095   
00096   ArArgumentParser argParser(&argc, argv);
00097   argParser.loadDefaultArguments();
00098 
00099   ArClientSimpleConnector clientConnector(&argParser);
00100 
00101   if(argParser.checkParameterArgumentDouble("-rate", &rate))
00102   {
00103     rateAsTime = ArMath::roundInt(1000.0 / rate);
00104   }
00105 
00106   useCounter = argParser.checkArgument("-counter");
00107 
00108   if(!Aria::parseArgs() || !argParser.checkHelpAndWarnUnparsed())
00109   {
00110     Aria::logOptions();
00111     ArLog::log(ArLog::Terse, "\n\n%s options:\n-rate <FramesPerSecondAsDouble> (If this isn't given, then the program will take one frame then exit, note that it is a double (so you can do .5 to do one frame per 2 seconds) and that if you set it to be too fast you'll saturate the robot's bandwidth and make it useless)\n-counter (default no)\n", argv[0]);
00112 
00113     ArLog::log(ArLog::Terse, "\n\nNotes:\nThis program saves the images as video.jpg if you aren't using a counter, or video<counter>.jpg if you are using the counter.\nIt puts its logs into getVideoLog.txt, and overwrites it whenever it runs\n");
00114     
00115     return 1;
00116   }
00117   
00118 
00119 
00120   ArClientBase client;
00121   if (!clientConnector.connectClient(&client))
00122   {
00123     ArLog::log(ArLog::Normal, "Could not connect to server, exiting\n");
00124     exit(1);
00125   }    
00126 
00127   ArGlobalFunctor1<ArNetPacket *> jpegHandlerCB(&jpegHandler);
00128 
00129   if(client.dataExists("getPictureCam1"))
00130   {
00131     ArLog::log(ArLog::Normal, "Requesting images using \"getPictureCam1\" request.");
00132     client.addHandler("getPictureCam1", &jpegHandlerCB);
00133     if (rate != 0 && rateAsTime != 0)
00134       client.request("getPictureCam1", rateAsTime); 
00135     else
00136       client.requestOnce("getPictureCam1");
00137   } 
00138   else if(client.dataExists("sendVideo"))
00139   {
00140     ArLog::log(ArLog::Normal, "Server does not have \"getPictureCam1\" request, requesting images using old \"sendVideo\" request.");
00141     client.addHandler("sendVideo", &jpegHandlerCB);
00142     if (rate != 0 && rateAsTime != 0)
00143       client.request("sendVideo", rate); 
00144     else
00145       client.requestOnce("sendVideo"); 
00146   }
00147   else
00148   {
00149     ArLog::log(ArLog::Terse, "Error: Server does not have \"getPictureCam1\" or \"sendVideo\" request, cannot request images.");
00150     Aria::exit(2);
00151   }
00152 
00153 
00154   client.run();
00155 
00156   Aria::shutdown();
00157   return 0;
00158 }
00159 
00160 
00161 

Generated on Fri Jul 31 12:37:28 2009 for ArNetworking by  doxygen 1.4.7