Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members   Related Pages  

AxisSource.cpp

Go to the documentation of this file.
00001 /**************************************************************************
00008  *
00009  * Source code for Real Time Image Library (libRTImage)
00010  *
00011  * Leeds Vision Group give permission for this code to be copied, modified
00012  * and distributed within the University of Leeds subject to the following
00013  * conditions:-
00014  *
00015  * - The code is not to be used for commercial gain.
00016  * - The code and use thereof will be attributed to the author where
00017  *   appropriate (inluding demonstrations which rely on it's use).
00018  * - All modified, distributions of the source files will retain this header.
00019  *
00020  ****************************************************************************/
00021 
00022 #include "AxisSource.h"
00023 
00024 AxisSource::AxisSource(char* axis_name, FrameSize frame_size) 
00034 {
00035         if(frame_size == 0){         //Half.
00036                 dims[0] = 352;
00037                 dims[1] = 288;
00038         }else if(frame_size == 1){   //Full.
00039                 dims[0] = 704;
00040                 dims[1] = 576;
00041         }else if(frame_size == 2){   //Cif
00042                 dims[0] = 320;
00043                 dims[1] = 240;
00044         }else{
00045                 cerr << "Unsupported Frame Size chosen" << endl;
00046                 cerr << "Choose HALF (352x288), FULL (704x576), or CIF (320x240) " << endl;
00047                 abort();
00048         }
00049 
00050         //Open a video socket to the web server
00051         vs = videoSocket(axis_name);
00052 
00053         //Send a video stream request
00054         requestStream(vs);
00055 
00056         // default palette for this ImageSource is colour
00057         type      = Image::COLOUR;
00058 }
00059 
00065 AxisSource::AxisSource()
00066 {
00067         vs = videoSocket("iri32");
00068         dims[0] = 352;
00069         dims[1] = 288;
00070         requestStream(vs);
00071         type      = Image::COLOUR;       
00072 }
00073 
00079 AxisSource::~AxisSource()
00080 {
00081         //close videosocket.
00082         close(vs);
00083 }
00084 
00092 ImageSource& AxisSource::operator >> (ImageRGB& img)
00093 {
00094         unsigned char *image;
00095         readNextFrame(vs,image,dims);
00096         
00097         PixelRGB *img_ptr = img.data; 
00098         int y_cnt;
00099         int x_cnt;
00100         unsigned char* src_ptr = image + 4*dims[0]*dims[1];
00101         src_ptr += 4*dims[0];
00102 
00103         for(y_cnt=0 ; y_cnt< dims[1] ; y_cnt++){
00104           src_ptr -= 2*4*dims[0];
00105           for(x_cnt=0 ; x_cnt< dims[0] ; x_cnt++){
00106             PixelRGB pix((int) *(src_ptr++),
00107                          (int) *(src_ptr++),
00108                          (int) *(src_ptr++));
00109             *(img_ptr++) = pix ;
00110             src_ptr++;
00111           }
00112         }
00113         delete [] image;
00114         return *this;
00115 }
00116 
00124 ImageSource& AxisSource::operator >> (ImageGrey& img)
00125 {
00126         unsigned char *image;
00127         readNextFrame(vs,image,dims);
00128  
00129         PixelGrey *img_ptr = img.brightness;
00130         int y_cnt;
00131         int x_cnt;
00132         unsigned char* src_ptr = image + 4*dims[0]*dims[1];
00133         src_ptr += 4*dims[0];
00134  
00135         for(y_cnt=0 ; y_cnt< dims[1] ; y_cnt++){
00136           src_ptr -= 2*4*dims[0];
00137           for(x_cnt=0 ; x_cnt< dims[0] ; x_cnt++){
00138             *(img_ptr++) = (PixelGrey)( (RED_COEF*(float)(*src_ptr++)) + 
00139                              (GREEN_COEF*(float)(*src_ptr++)) +
00140                              (BLUE_COEF*(float)(*src_ptr++)) );
00141             src_ptr++;
00142           }
00143         }
00144         delete [] image;
00145         return *this;                                   
00146 }
00147 
00157 ImageSource& AxisSource::operator >> (Image& img)
00158 {
00159         (type == Image::COLOUR) ? *this >> (ImageRGB&)img
00160                                 : *this >> (ImageGrey&)img;
00161 
00162         return *this;
00163 }
00164                     
00165 
00166 int AxisSource::videoSocket(char *hostname)
00167 {
00168     int sockfd;  
00169     hostent *he;
00170     protoent *protoEntry;
00171     sockaddr_in their_addr; /* connector's address information */
00172 
00173     // Get the host info 
00174     if ((he = gethostbyname(hostname)) == NULL) 
00175     {  
00176         string msg("\'gethostbyname\' failed for ");
00177         msg += hostname;
00178         
00179         throw msg.c_str();
00180     }
00181 
00182     protoEntry = getprotobyname("tcp");
00183     short protocol = protoEntry->p_proto;
00184 
00185     // Open the socket
00186     if ((sockfd = socket(PF_INET, SOCK_STREAM, protocol)) == -1) 
00187     {
00188         throw "Failed to open socket";
00189     }
00190 
00191     int on=1;
00192     setsockopt(sockfd, protoEntry->p_proto, TCP_NODELAY, &on, sizeof(int));
00193 
00194     // Configure the socket
00195     their_addr.sin_family = AF_INET;    /* host byte order */
00196     their_addr.sin_port = htons(PORT);  /* short, network byte order */
00197     their_addr.sin_addr = *((struct in_addr *)he->h_addr);
00198     memset(&(their_addr.sin_zero), 0, 8); /* zero the rest of the struct */
00199 
00200     // Now try and connect to the server
00201     if (connect(sockfd, (sockaddr *) &their_addr, sizeof(sockaddr)) == -1) 
00202     {
00203         throw "Unable to connect to server..\n";
00204     }
00205 
00206     return sockfd;
00207 }
00208 
00209 
00210 void AxisSource::requestStream(int sockfd)
00211 {
00212     // Formulate the request
00213     char req[1000] ;
00214 
00215     sprintf(req,
00216             "GET /cgi-bin/mjpg/video.cgi?showlength=1&resolution=%dx%d "
00217             "HTTP/1.0\n\n",
00218             dims[0],dims[1]) ;
00219 
00220     cout << "Request: " << req;
00221 
00222     // Send it to the server
00223     if (send(sockfd, req, strlen(req), 0) == -1) 
00224     {
00225         string msg("Unable to send following request to server: \n\n");
00226         msg += req;
00227         
00228         throw msg;
00229     }
00230 
00231     // Read and strip off the general header info
00232     unsigned char seqHeader[82];
00233 
00234     readSocket(sockfd, seqHeader,81); 
00235 
00236     seqHeader[81]='\0';
00237     cout << "Received sequence header:\n" << seqHeader;
00238 }
00239 
00240 
00241 void AxisSource::readNextFrame(int sockfd, unsigned char* &image, int imgSize[2])
00242 {
00243     int buffLength;
00244     int readCount=1;
00245     unsigned char *imgBuff;
00246 
00247     while (readCount==1)
00248     {
00249         readCount = readFrame(sockfd, imgBuff, buffLength);
00250         if (readCount==1) delete [] imgBuff;
00251     }
00252 
00253     decodeFrame(imgBuff, buffLength, image, imgSize);
00254 
00255     delete [] imgBuff;
00256 }
00257 
00258 
00259 int AxisSource::readFrame(int sockfd, unsigned char* &imgBuff, int &buffLength)
00260 {
00261     int readCount;
00262     int imgLength;
00263     unsigned char *recvBuff;
00264     unsigned char imgHeader[128];
00265 
00266     // Read the boundary tag and image header
00267     readSocket(sockfd, imgHeader, 13);
00268     imgHeader[13]='\0';
00269 
00270     // Read the Content-Type header
00271     readSocket(sockfd, imgHeader, 25); 
00272     imgHeader[25]='\0';
00273 
00274     // Read the Content-Length
00275     readSocket(sockfd, imgHeader, 24); 
00276     imgHeader[24]='\0';
00277 
00278     imgLength = 0;
00279     char tmpBuff[128];
00280     for (int i = 0; i < 128; i++) tmpBuff[i] = imgHeader[i];
00281     sscanf(tmpBuff, "Content-Length: %d\n", &imgLength);
00282 
00283     if (imgLength < 10000)
00284     {
00285          recvBuff = new unsigned char[imgLength];
00286          recvBuff[0] = imgHeader[22];
00287          recvBuff[1] = imgHeader[23];
00288          
00289          unsigned char *tmpHolder = &(recvBuff[2]);
00290          readCount = readSocket(sockfd, tmpHolder, imgLength-2);
00291     }
00292     else if(imgLength < 100000)
00293     {
00294          recvBuff = new unsigned char[imgLength];
00295          recvBuff[0] = imgHeader[23];
00296          
00297          unsigned char *tmpHolder = &(recvBuff[1]);
00298          readCount = readSocket(sockfd, tmpHolder, imgLength-1);
00299     }
00300     else
00301     {
00302          // Now create a buffer and read the jpg image (length is imgLength)
00303          recvBuff = new unsigned char[imgLength];
00304          readCount = readSocket(sockfd, recvBuff, imgLength); 
00305     }
00306 
00307     imgBuff = recvBuff;
00308     buffLength = imgLength;
00309 
00310     // Strip off the trailing <CR> from the input stream
00311     unsigned char tmp[128];
00312     readSocket(sockfd, tmp, 2);
00313 
00314     return readCount;
00315 }
00316     
00317 
00318 int AxisSource::readSocket(int sockfd, unsigned char *buff, int buffLength)
00319 {
00320     int count = 0, bytesRead = 0;
00321 
00322     while (count < buffLength)
00323     {
00324         bytesRead = recv(sockfd, buff+count, buffLength-count, MSG_TRUNC);
00325         count += bytesRead;
00326     }
00327     
00328     return (bytesRead == count);
00329 }
00330 
00331 void AxisSource::decodeFrame(unsigned char* imgBuff, int buffLength,
00332                  unsigned char* &image,  int imgSize[2])
00333 {
00334     struct jpeg_error_mgr jerr;
00335     jpeg_decompress_struct cinfo;
00336     cinfo.err = jpeg_std_error(&jerr);
00337  
00338     jpeg_create_decompress(&cinfo);
00339     jpeg_mem_src(&cinfo, imgBuff, buffLength);
00340     jpeg_read_header(&cinfo, TRUE);
00341  
00342     jpeg_start_decompress(&cinfo);
00343  
00344     int rowStride = cinfo.output_width * cinfo.num_components;
00345     int total = rowStride*cinfo.output_height;
00346  
00347     JSAMPLE *cdata = new JSAMPLE[total];
00348     JSAMPLE *base = cdata;
00349  
00350     int numread;
00351     while(cinfo.output_scanline < cinfo.output_height)
00352     {
00353         numread = jpeg_read_scanlines(&cinfo, &cdata, cinfo.rec_outbuf_height);
00354         cdata += numread*rowStride;
00355     }
00356  
00357     int ArowStride = cinfo.output_width * (cinfo.num_components+1);
00358     int Atotal = ArowStride*cinfo.output_height;
00359     JSAMPLE *idata = new JSAMPLE[Atotal];
00360  
00361     // GL expects the array to start at the bottom left,
00362     // but the decoded data starts at the top left
00363     for(int j=Atotal-ArowStride, i=0; j>=0; j-=2*ArowStride)
00364     {
00365         for (int k=0; k<rowStride; k+=3, i+=3, j+=4)
00366         {
00367         idata[j]   = base[i];
00368         idata[j+1] = base[i+1];
00369         idata[j+2] = base[i+2];
00370         idata[j+3] = 0;
00371         }
00372     }
00373     delete [] base;
00374     base = idata;              
00375                  
00376     // Image data now decompressed and stored in cdata
00377     image = base;
00378     imgSize[0] = cinfo.output_width;
00379     imgSize[1] = cinfo.output_height;
00380  
00381     jpeg_finish_decompress(&cinfo);
00382 }
00383                                
00384 
00385 
00386 
00387 
00388 

Generated at Fri Aug 13 17:29:20 2004 for libRTImage by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001