Main Page | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages | Examples

ArHybridForwarderVideo.cpp

Go to the documentation of this file.
00001 /*
00002 MobileRobots Advanced Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004, 2005 ActivMedia Robotics LLC
00004 Copyright (C) 2006, 2007 MobileRobots Inc.
00005 
00006      This program is free software; you can redistribute it and/or modify
00007      it under the terms of the GNU General Public License as published by
00008      the Free Software Foundation; either version 2 of the License, or
00009      (at your option) any later version.
00010 
00011      This program is distributed in the hope that it will be useful,
00012      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014      GNU General Public License for more details.
00015 
00016      You should have received a copy of the GNU General Public License
00017      along with this program; if not, write to the Free Software
00018      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 If you wish to redistribute ARIA under different terms, contact 
00021 MobileRobots for information about a commercial version of ARIA at 
00022 robots@mobilerobots.com or 
00023 MobileRobots Inc, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
00024 */
00025 
00026 #include "Aria.h"
00027 #include "ArExport.h"
00028 #include "ArHybridForwarderVideo.h"
00029 
00036 AREXPORT ArHybridForwarderVideo::ArHybridForwarderVideo(ArServerBase *server, 
00037                                                                                                   ArClientBase *client)
00038 {
00039   myServer = server;
00040   myClient = client;
00041   finishConstructor();
00042 }
00043 
00053 AREXPORT ArHybridForwarderVideo::ArHybridForwarderVideo(ArServerBase *server,
00054                                                                                                   const char *hostname,
00055                                                                                                   int port)
00056 {
00057   myServer = server;
00058   myClient = new ArClientBase();
00059   myClient->setConnectTimeoutTime(1);
00060   myClient->blockingConnect(hostname, port, false);
00061   myClient->runAsync();
00062   finishConstructor();
00063 }
00064 
00065 AREXPORT ArHybridForwarderVideo::~ArHybridForwarderVideo()
00066 {
00067 
00068 }
00069 
00070 AREXPORT void ArHybridForwarderVideo::finishConstructor(void)
00071 {
00072   myClient->lock();
00073   mySendVideoSizeCB = new ArFunctor2C<ArHybridForwarderVideo, ArServerClient*, 
00074   ArNetPacket *>(this, &ArHybridForwarderVideo::sendVideoSize);
00075 
00076   mySendVideoCB = new ArFunctor2C<ArHybridForwarderVideo, ArServerClient*, 
00077   ArNetPacket *>(this, &ArHybridForwarderVideo::sendVideo);
00078   
00079   myReceiveVideoSizeCB = new ArFunctor1C<ArHybridForwarderVideo, 
00080   ArNetPacket *>(this, &ArHybridForwarderVideo::receiveVideoSize);
00081 
00082   myReceiveVideoCB = new ArFunctor1C<ArHybridForwarderVideo, 
00083   ArNetPacket *>(this, &ArHybridForwarderVideo::receiveVideo);
00084 
00085   myClientCycleCB = new ArFunctorC<ArHybridForwarderVideo>(
00086           this, &ArHybridForwarderVideo::clientCycleCallback);
00087 
00088   myReqSent = false;
00089   myLastReqSent.setToNow();
00090   myLastReceivedVideo.setToNow();
00091   myVideoRequestTime = 100;
00092   myForwardingVideo = false;
00093 
00094   if (myClient != NULL && myServer != NULL && myClient->isConnected())
00095   {
00096     myClient->addCycleCallback(myClientCycleCB);
00097     if (myClient->dataExists("videoSize"))
00098     {
00099       myServer->addData("videoSize", 
00100                         "gets the width and height of the video data", 
00101                         mySendVideoSizeCB, 
00102                         "none", "uByte2: width, uByte2: height",
00103                         "Video", "RETURN_SINGLE");
00104       myClient->addHandler("videoSize", myReceiveVideoSizeCB);
00105       myClient->requestOnce("videoSize");
00106     }
00107     if (myClient->dataExists("sendVideo"))
00108     {
00109       ArLog::log(ArLog::Normal, "Forwarding video.");
00110       myForwardingVideo = true;
00111       myClient->addHandler("sendVideo", myReceiveVideoCB);
00112       ArNetPacket packet;
00113       packet.uByteToBuf(90);
00114       myClient->requestOnce("sendVideo", &packet);
00115 
00116       myIsSendVideoAvailable = 
00117         myServer->addData("sendVideo", "gets video from the robot's camera (you should requestOnce this, you shouldn't request it, since you could easily fill the bandwidth that way)",
00118                                             mySendVideoCB, "uByte: quality (0 - 100)", 
00119                           "out: uByte2: width, uByte2: height, (len - readLen)*uByte: jpegData", "Video", "RETURN_VIDEO");
00120     }
00121   }
00122   myClient->unlock();
00123 }
00124 
00125 
00126 AREXPORT const char *ArHybridForwarderVideo::getCameraName()
00127 {
00128   return myCameraName.c_str();
00129 }
00130 
00131 AREXPORT void ArHybridForwarderVideo::setCameraName(const char *cameraName)
00132 {
00133   if (cameraName != NULL) {
00134     myCameraName = cameraName;
00135   }
00136   else {
00137     myCameraName = "";
00138   }
00139 
00140 } // end method setCameraName
00141 
00142 
00143 AREXPORT void ArHybridForwarderVideo::addToCameraCollection
00144                                           (ArCameraCollection &collection)
00145 {
00146   if (myCameraName.empty()) {
00147     return;
00148   } // end if no camera name
00149 
00150   const char *cameraName = myCameraName.c_str();
00151   if (!collection.exists(cameraName)) {
00152 
00153     return;
00154   } // end if camera not yet created
00155 
00156   bool isSuccess = true;
00157   
00158   if (myForwardingVideo) {
00159 
00160     std::string packetName = "getPicture" + myCameraName;
00161 
00162     // This is a little unusual to add the handler here, but this method
00163     // should only be called once, so hopefully it's no problem...
00164     isSuccess = myServer->addData(packetName.c_str(), 
00165                                   "Gets video from the robot's camera",
00166                                                     mySendVideoCB, "uByte: quality (0 - 100)", 
00167                                                     "out: uByte2: width, uByte2: height, (len - readLen)*uByte: jpegData", "Video");
00168 
00169     if (isSuccess) {
00170       isSuccess = collection.addCameraCommand
00171                               (cameraName,
00172                               ArCameraCommands::GET_PICTURE,
00173                               packetName.c_str(),
00174                               myVideoRequestTime); // TODO ? 
00175     }
00176 
00177     if (!isSuccess) {
00178       ArLog::log(ArLog::Verbose,
00179                 "Video forwarder could not add camera %s command %s",
00180                 cameraName,
00181                 packetName.c_str());
00182     } // end if error occurred
00183 
00184   } // end if forwarding video
00185 
00186   // Left the original addData("sendVideo") in the finishConstructor()
00187   // method - just to try to avoid any backwards compatibility issues.
00188   if (myIsSendVideoAvailable) {
00189 
00190     isSuccess = collection.addCameraCommand
00191                             (cameraName,
00192                             ArCameraCommands::GET_VIDEO,
00193                             "sendVideo",
00194                             myVideoRequestTime); // TODO ? 
00195   }
00196 
00197 } // end method addToCameraCollection
00198 
00199 
00200 
00201 AREXPORT void ArHybridForwarderVideo::sendVideoSize(ArServerClient *client, 
00202                                                     ArNetPacket *packet)
00203 {
00204   myMutex.lock();
00205   myReceivedVideoSize.setCommand(packet->getCommand());
00206   client->sendPacketTcp(&myReceivedVideoSize);
00207   myMutex.unlock();
00208 }
00209 
00210 AREXPORT void ArHybridForwarderVideo::sendVideo(ArServerClient *client, 
00211                                                 ArNetPacket *packet)
00212 {
00213   //printf("Sending video\n");
00214   myMutex.lock();
00215   mySendVideoArgument.duplicatePacket(packet);
00216   mySendVideoArgument.resetRead();
00217   // MPL fixed the code so that this next line worked, but should
00218   // probably let the base figure out the command (since it does it
00219   // for everything else)
00220   //myReceivedVideo.setCommand(packet->getCommand());
00221   myReceivedVideo.setCommand(0);
00222   client->sendPacketUdp(&myReceivedVideo);
00223   //printf("Sent video %d\n", myReceivedVideo.getLength());
00224   myMutex.unlock();
00225 }
00226 
00227 AREXPORT void ArHybridForwarderVideo::receiveVideoSize(ArNetPacket *packet)
00228 {
00229   //printf("Receiving video size\n");
00230   myMutex.lock();
00231   myReceivedVideoSize.duplicatePacket(packet);
00232   mySendVideoArgument.resetRead();
00233   myMutex.unlock();
00234 }
00235 
00236 AREXPORT void ArHybridForwarderVideo::receiveVideo(ArNetPacket *packet)
00237 {
00238   //printf("Receiving video\n");
00239   myMutex.lock();
00240   myReceivedVideo.duplicatePacket(packet);
00241   myReceivedVideo.resetRead();
00242   myLastReceivedVideo.setToNow();
00243   myReqSent = false;
00244   myMutex.unlock();
00245 }
00246 
00247 AREXPORT void ArHybridForwarderVideo::clientCycleCallback(void)
00248 {
00249   myMutex.lock();
00250   if ((myLastReceivedVideo.mSecSince() > myVideoRequestTime && !myReqSent) ||
00251       (myReqSent && myLastReqSent.mSecSince() > 3000))
00252   {
00253     //printf("Requesting video\n");
00254     myClient->requestOnce("sendVideo", &mySendVideoArgument);
00255     myLastReqSent.setToNow();
00256     myReqSent = true;
00257   } 
00258   myMutex.unlock();
00259 }
00260 
00261 AREXPORT bool ArHybridForwarderVideo::isForwardingVideo(void) const
00262 {
00263   return myForwardingVideo;
00264 }

Generated on Tue Feb 20 10:51:50 2007 for ArNetworking by  doxygen 1.4.0