Now you can download a copy of these docs so you can use them offline! Download now
PCVideoServer.cpp
00001 /*----------------------------------------------------------------------------*/ 00002 /* Copyright (c) FIRST 2008. All Rights Reserved. */ 00003 /* Open Source Software - may be modified and shared by FRC teams. The code */ 00004 /* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ 00005 /*----------------------------------------------------------------------------*/ 00006 00007 #include <vxWorks.h> 00008 00009 #include "PCVideoServer.h" 00010 00011 #include <errnoLib.h> 00012 #include <hostLib.h> 00013 #include <inetLib.h> 00014 #include <sockLib.h> 00015 00016 #include "Vision/AxisCamera.h" 00017 #include "Task.h" 00018 #include "Timer.h" 00019 #include "WPIErrors.h" 00020 00025 class ScopedSocket { 00026 public: 00027 ScopedSocket(int camSock) 00028 : m_camSock(camSock) 00029 { 00030 } 00031 00032 ~ScopedSocket() { 00033 if (m_camSock != ERROR) { 00034 close(m_camSock); 00035 } 00036 } 00037 // Cast to int allows you to pass this to any function that 00038 // takes the socket as an int. 00039 operator int() const { 00040 return m_camSock; 00041 } 00042 00043 private: 00044 int m_camSock; 00045 }; 00046 00047 //============================================================================ 00048 // PCVideoServer 00049 //============================================================================ 00050 00054 PCVideoServer::PCVideoServer() 00055 : m_serverTask("PCVideoServer", (FUNCPTR)s_ServerTask) 00056 , m_newImageSem (NULL) 00057 , m_stopServer (false) 00058 { 00059 AxisCamera &cam = AxisCamera::GetInstance(); 00060 m_newImageSem = cam.GetNewImageSem(); 00061 if (!cam.StatusIsFatal()) 00062 { 00063 StartServerTask(); 00064 } 00065 else 00066 { 00067 CloneError(&cam); 00068 } 00069 } 00070 00075 PCVideoServer::~PCVideoServer() 00076 { 00077 // Stop the images to PC server. 00078 Stop(); 00079 // Clear the error so that you can use this object to make a connection to 00080 // the VIDEO_TO_PC_PORT to stop the ImageToPCServer if it is waiting to 00081 // accept connections from a PC. 00082 ClearError(); 00083 // Open a socket. 00084 int camSock = socket(AF_INET, SOCK_STREAM, 0); 00085 if (camSock == ERROR) 00086 { 00087 wpi_setErrnoError(); 00088 return; 00089 } 00090 ScopedSocket scopedCamSock(camSock); 00091 // If successful 00092 if (!StatusIsFatal()) 00093 { 00094 // Create a connection to the localhost. 00095 struct sockaddr_in selfAddr; 00096 int sockAddrSize = sizeof(selfAddr); 00097 bzero ((char *) &selfAddr, sockAddrSize); 00098 selfAddr.sin_family = AF_INET; 00099 selfAddr.sin_len = (u_char) sockAddrSize; 00100 selfAddr.sin_port = htons (VIDEO_TO_PC_PORT); 00101 00102 if (( (int)(selfAddr.sin_addr.s_addr = inet_addr (const_cast<char*>("localhost")) ) != ERROR) || 00103 ( (int)(selfAddr.sin_addr.s_addr = hostGetByName (const_cast<char*>("localhost")) ) != ERROR)) 00104 { 00105 struct timeval connectTimeout; 00106 connectTimeout.tv_sec = 1; 00107 connectTimeout.tv_usec = 0; 00108 connectWithTimeout(camSock, (struct sockaddr *) &selfAddr, sockAddrSize, &connectTimeout); 00109 } 00110 } 00111 } 00112 00116 int PCVideoServer::StartServerTask() 00117 { 00118 if (StatusIsFatal()) 00119 { 00120 return -1; 00121 } 00122 int id = 0; 00123 m_stopServer = false; 00124 // Check for prior copy of running task 00125 int oldId = taskNameToId((char*)m_serverTask.GetName()); 00126 if(oldId != ERROR) 00127 { 00128 // TODO: Report error. You are in a bad state. 00129 taskDelete(oldId); 00130 } 00131 00132 // spawn video server task 00133 // this is done to ensure that the task is spawned with the 00134 // floating point context save parameter. 00135 bool started = m_serverTask.Start((int)this); 00136 00137 id = m_serverTask.GetID(); 00138 00139 if (!started) 00140 { 00141 wpi_setWPIError(TaskError); 00142 return id; 00143 } 00144 taskDelay(1); 00145 return id; 00146 } 00147 00151 void PCVideoServer::Start() 00152 { 00153 StartServerTask(); 00154 } 00155 00159 void PCVideoServer::Stop() 00160 { 00161 m_stopServer = true; 00162 } 00163 00167 int PCVideoServer::s_ServerTask(PCVideoServer *thisPtr) 00168 { 00169 return thisPtr->ServerTask(); 00170 } 00171 00177 int PCVideoServer::ServerTask() 00178 { 00179 /* Setup to PC sockets */ 00180 struct sockaddr_in serverAddr; 00181 int sockAddrSize = sizeof(serverAddr); 00182 int pcSock = ERROR; 00183 bzero ((char *) &serverAddr, sockAddrSize); 00184 serverAddr.sin_len = (u_char) sockAddrSize; 00185 serverAddr.sin_family = AF_INET; 00186 serverAddr.sin_port = htons (VIDEO_TO_PC_PORT); 00187 serverAddr.sin_addr.s_addr = htonl (INADDR_ANY); 00188 00189 int success; 00190 while (true) 00191 { 00192 taskSafe(); 00193 // Create the socket. 00194 if ((pcSock = socket (AF_INET, SOCK_STREAM, 0)) == ERROR) 00195 { 00196 wpi_setErrnoErrorWithContext("Failed to create the PCVideoServer socket"); 00197 continue; 00198 } 00199 // Set the TCP socket so that it can be reused if it is in the wait state. 00200 int reuseAddr = 1; 00201 setsockopt(pcSock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&reuseAddr), sizeof(reuseAddr)); 00202 // Bind socket to local address. 00203 if (bind (pcSock, (struct sockaddr *) &serverAddr, sockAddrSize) == ERROR) 00204 { 00205 wpi_setErrnoErrorWithContext("Failed to bind the PCVideoServer port"); 00206 close (pcSock); 00207 continue; 00208 } 00209 // Create queue for client connection requests. 00210 if (listen (pcSock, 1) == ERROR) 00211 { 00212 wpi_setErrnoErrorWithContext("Failed to listen on the PCVideoServer port"); 00213 close (pcSock); 00214 continue; 00215 } 00216 00217 struct sockaddr_in clientAddr; 00218 int clientAddrSize; 00219 int newPCSock = accept (pcSock, reinterpret_cast<sockaddr*>(&clientAddr), &clientAddrSize); 00220 if (newPCSock == ERROR) 00221 { 00222 close(pcSock); 00223 continue; 00224 } 00225 //TODO: check camera error 00226 00227 int numBytes = 0; 00228 int imageDataSize = 0; 00229 char* imageData = NULL; 00230 00231 while(!m_stopServer) 00232 { 00233 success = semTake(m_newImageSem, 1000); 00234 if (success == ERROR) 00235 { 00236 // If the semTake timed out, there are no new images from the camera. 00237 continue; 00238 } 00239 success = AxisCamera::GetInstance().CopyJPEG(&imageData, numBytes, imageDataSize); 00240 if (!success) 00241 { 00242 // No point in running too fast - 00243 Wait(1.0); 00244 // If camera is not initialzed you will get failure and 00245 // the timestamp is invalid. Reset this value and try again. 00246 continue; 00247 } 00248 00249 // Write header to PC 00250 static const char header[4]={1,0,0,0}; 00251 int headerSend = write(newPCSock, const_cast<char*>(header), 4); 00252 00253 // Write image length to PC 00254 int lengthSend = write(newPCSock, reinterpret_cast<char*>(&numBytes), 4); 00255 00256 // Write image to PC 00257 int sent = write (newPCSock, imageData, numBytes); 00258 00259 // The PC probably closed connection. Get out of here 00260 // and try listening again. 00261 if (headerSend == ERROR || lengthSend == ERROR || sent == ERROR) 00262 { 00263 break; 00264 } 00265 } 00266 // Clean up 00267 delete [] imageData; 00268 close (newPCSock); 00269 newPCSock = ERROR; 00270 close (pcSock); 00271 pcSock = ERROR; 00272 taskUnsafe(); 00273 Wait(0.1); 00274 } 00275 return (OK); 00276 } 00277
Generated on Thu Jan 12 2012 22:35:23 for WPILibC++ by
1.7.1