Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

phNetSource.cpp

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------
00002     Phission : 
00003         Realtime Vision Processing System
00004     
00005     Copyright (C) 2003-2006 Philip D.S. Thoren (pthoren@cs.uml.edu)
00006     University of Massachusetts at Lowell,
00007     Laboratory for Artificial Intelligence and Robotics
00008     
00009     This file is part of Phission.
00010 
00011     Phission is free software; you can redistribute it and/or modify
00012     it under the terms of the GNU Lesser General Public License as published by
00013     the Free Software Foundation; either version 2 of the License, or
00014     (at your option) any later version.
00015 
00016     Phission is distributed in the hope that it will be useful,
00017     but WITHOUT ANY WARRANTY; without even the implied warranty of
00018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019     GNU Lesser General Public License for more details.
00020 
00021     You should have received a copy of the GNU Lesser General Public License
00022     along with Phission; if not, write to the Free Software
00023     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024 
00025  ---------------------------------------------------------------------------*/
00026 #ifdef HAVE_CONFIG_H
00027     #include <phissionconfig.h>
00028 #endif
00029 
00030 #define phNetSource_PRINT_IMAGE_SIZE() 0
00031 #define phNetSource_USE_JITTER_SYNC() 0
00032 
00033 #define VERBOSE() 0
00034 
00035 /* ---------------------------------------------------------------------- */
00036 #include <phStandard.h>
00037 #include <ImageConversions.h>
00038 
00039 #include <phObject.h>
00040 #include <phMutex.h>
00041 #include <phSemaphore.h>
00042 #include <phCondition.h>
00043 #include <phRWLock.h>
00044 #include <phThread.h>
00045 #include <phList.h>
00046 #include <phTimeStamp.h>
00047 #include <phTimeInterval.h>
00048 #include <phLiveObject.h>
00049 #include <phDataObject.h>
00050 #include <phImage.h>
00051 #include <phCaptureInterface.h>
00052 #include <phImageCapture.h>
00053 
00054 #include <phTimeInterval.h>
00055 #include <phSocket.h>
00056 #include <phNetSource.h>
00057 
00058 #include <phError.h>
00059 #include <phMemory.h>
00060 #include <phPrint.h>
00061 
00062 /* ---------------------------------------------------------------------- */
00063 /* TODO:  */
00064 struct phNetSourceInfo_t
00065 {
00066     phSocket    *m_comms;
00067     char        *m_host;
00068     uint32_t    m_port;
00069     /* The width,height, format and title are retreived from the server.  */
00070     uint32_t    m_width;
00071     uint32_t    m_height;
00072     uint32_t    m_format;
00073     char        *m_title;
00074 
00075     int         m_do_resize;
00076     int         m_do_convert;
00077 };
00078 
00079 /* ---------------------------------------------------------------------- */
00080 phNetSource::phNetSource(char *path)
00081 {
00082     phFUNCTION("phNetSource::phNetSource")
00083     
00084     rc = this->lock();
00085     phPRINT_RC(rc,NULL,"this->lock()");
00086    
00087     this->setName("phNetSource");
00088    
00089     this->m_info = (struct phNetSourceInfo_t *)phCalloc(1,
00090                         sizeof(struct phNetSourceInfo_t));
00091     phPRINT_PTR(this->m_info,"phCalloc",
00092               "phCalloc failed to alloc phNetSourceInfo");
00093     this->m_info->m_host        = NULL;
00094     this->m_info->m_port        = 0;
00095     this->m_info->m_comms       = NULL;
00096     this->m_info->m_width       = 0;
00097     this->m_info->m_height      = 0;
00098     this->m_info->m_format      = phImageNOFORMAT;
00099     this->m_info->m_title       = NULL;
00100     this->m_info->m_do_resize   = 0;
00101     this->m_info->m_do_convert  = 0;
00102     
00103     this->m_orig_format = phImageNOFORMAT;
00104     this->m_orig_height = 0;
00105     this->m_orig_width  = 0;
00106     this->m_orig_size   = 0;
00107 
00108     this->m_is_open     = 0;
00109     
00110     this->m_type        = phNetTypeTCP;
00111     this->m_temp_path   = NULL;
00112    
00113     this->m_connected_type = phNetTypeUNKNOWN;
00114     
00115     this->m_reconnect   = 1;
00116     this->m_server_wait = 1;
00117         
00118     if (path != NULL)
00119     {
00120         this->setPath(path);
00121     }
00122     else
00123     {
00124         this->setPath("tcp://localhost:22345");
00125     }
00126 
00127     /* This applies the default (1) picture/image settings[w,h,format,etc.]
00128      * (2) channel settings  */
00129     this->applySettings();
00130     
00131     /* opening the device must be explicitly done */
00132     /* capturing must be explicitly done. */
00133 #if 0
00134 error:
00135 #endif
00136     rc = this->unlock();
00137     phPRINT_RC(rc,NULL,"this->unlock()");
00138     
00139     return;
00140 }
00141 
00142 /* ---------------------------------------------------------------------- */
00143 phNetSource::~phNetSource ()
00144 {
00145     phFUNCTION("phNetSource::~phNetSource")
00146   
00147     rc = this->lock();
00148     phPRINT_RC(rc,NULL,"this->lock()");
00149 
00150     if (this->isRunning())
00151     {
00152         rc = this->stop();
00153         phPRINT_RC(rc,NULL,"this->stop()");
00154     }
00155    
00156     if (this->isOpen())
00157     {
00158         rc = this->close();
00159         phPRINT_RC(rc,NULL,"this->close()");
00160     }
00161  
00162     phFree(this->m_info);
00163     
00164     rc = this->unlock();
00165     phPRINT_RC(rc,NULL,"this->unlock()");
00166 }
00167 
00168 /* ---------------------------------------------------------------------- */
00169 int phNetSource::parsePath( const char  *path,
00170                             char        **host_ptr,
00171                             uint32_t    *port_ptr,
00172                             uint32_t    *type_ptr   )
00173 {
00174     phFUNCTION("phNetSource::parsePath")
00175     
00176     uint32_t i                  = 0;
00177     uint32_t type               = phNetTypeTCP;
00178     uint32_t port               = 22345;
00179     char    *host               = NULL;
00180     int32_t  host_start         = 0;
00181     uint32_t host_length        = 0;
00182     uint32_t host_ptr_length    = 0;
00183     uint32_t length             = (uint32_t)((path != NULL) ? strlen(path) : 0);
00184     
00185     /* Find the first ':' */
00186     for (i = 0; ((i < length) && (path[i] != ':')); i++ );
00187 
00188     if (i >= length)
00189     {
00190         phCHECK_RC(-1,NULL,"Invalid path string: %s", path);
00191     }
00192 
00193     if (strncmp("tcp",&(path[0]),i) == 0)
00194     {
00195         type = phNetTypeTCP;
00196     }
00197     else
00198     {
00199         type = phNetTypeUNKNOWN;
00200     }
00201 
00202     /* Go past the "//" to the host */
00203     for (i++; ((i < length) && (path[i] != '/')); i++ );
00204     for (i++; ((i < length) && (path[i] != '/')); i++ );
00205     
00206     if (i >= length)
00207     {
00208         phCHECK_RC(-1,NULL,"Invalid path string: %s", path);
00209     }
00210 
00211     /* Parse out the host */
00212     for (i++, host_start = i, host_length = 0;
00213          ((i < length) && (path[(i > 0) ? i - 1 : 0] != ':')); 
00214          i++, host_length++ );
00215 
00216     if ((i >= length) || (host_length <= 0))
00217     {
00218         phCHECK_RC(-1,NULL,"Invalid path string: %s", path);
00219     }
00220 
00221     host = (char *)phCalloc((host_length + 1),sizeof(char));
00222     phCHECK_PTR(host,"phCalloc",
00223               "phCalloc failed to allocate host string buffer of length %d",
00224               host_length );
00225     
00226 #if defined(HAVE_SNPRINTF)
00227     snprintf(host,host_length,"%s",&(path[host_start]));
00228 #else
00229     sprintf(host,"%s",&(path[host_start]));
00230 #endif
00231 
00232     /* Get the port from the end of the line */
00233     port = atoi(&(path[i]));
00234     
00235     if (host_ptr != NULL)
00236     {
00237         /* Figure out the path length */
00238         host_ptr_length = (uint32_t)((*host_ptr) != NULL ? strlen(*host_ptr) : 0);
00239     
00240         /* allocate enough space for the path */
00241         phDALLOC((*host_ptr),host_ptr_length,(host_length+1),char);
00242 
00243 #if defined(HAVE_SNPRINTF)
00244         snprintf(*host_ptr,host_length+1,"%s",host);
00245 #else
00246         sprintf(*host_ptr,"%s",host);
00247 #endif
00248     }
00249 
00250     /* Assign the values through the return pointers */
00251     if (type_ptr != NULL)
00252         *type_ptr = type;
00253     if (port_ptr != NULL)
00254         *port_ptr = port;
00255     
00256     phFree(host);
00257 
00258     //phPRINT("-%s:%d-\n",(*host_ptr),(*port_ptr));
00259 
00260     return phSUCCESS;
00261 error:
00262     phFree(host);
00263     
00264     return phFAIL;
00265 }
00266 
00267 /* ---------------------------------------------------------------------- */
00268 /* makePath : 
00269  *
00270  * This function allocates space to *path, be sure to free it */
00271 /* ---------------------------------------------------------------------- */
00272 int phNetSource::makePath( const char  *host, 
00273                            uint32_t    port,
00274                            uint32_t    type,
00275                            char        **path )
00276 {
00277     phFUNCTION("phNetSource::makePath")
00278 
00279     uint32_t pathLength     = 0;
00280     uint32_t length         = 0;
00281     uint32_t host_length    = 0;
00282     uint32_t type_length    = 0;
00283     char *   type_string    = NULL;
00284 
00285     if (path == NULL) return phFAIL;
00286   
00287     /* Default to the local machine */
00288     if (host == NULL)
00289     {
00290         host = "localhost";
00291     }
00292     host_length = (uint32_t)strlen(host);
00293     
00294     /* make sure the path is valid */
00295     port = (port != 0) ? ((port < 65535) ? port : 22345) : 22345;
00296    
00297     /* Set up the type string */
00298     switch (type)
00299     {
00300         case phNetTypeTCP:
00301         default:
00302             type_string = "tcp://";
00303             break;
00304     }
00305     type_length = (uint32_t)strlen(type_string);
00306 
00307     length = type_length + host_length + 1 + 7;
00308     
00309     /* Figure out the path length */
00310     pathLength = (uint32_t)((*path) != NULL ? strlen(*path) : 0);
00311     
00312     /* allocate enough space for the path */
00313     phDALLOC((*path),pathLength,length,char);
00314 
00315     sprintf(*path,"%s%s:%u",
00316             type_string,
00317             host,
00318             port );
00319     return phSUCCESS;
00320 error:
00321     return phFAIL;
00322 }
00323 /* ---------------------------------------------------------------------- */
00324 int phNetSource::setHost( const char *host )
00325 {
00326     phFUNCTION("phNetSource::setHost")
00327     int locked = 0;
00328    
00329     phTHIS_LOCK(locked);
00330 
00331     rc = phNetSource::makePath( host,
00332                                 this->m_info->m_port,
00333                                 this->m_type,
00334                                 &this->m_temp_path);
00335     phCHECK_RC(rc,NULL,"phNetSource::makePath");
00336 
00337     rc = this->setPath(this->m_temp_path);
00338     phCHECK_RC(rc,NULL,"this->setPath(%s)",this->m_temp_path);
00339 
00340     phTHIS_UNLOCK_RET(locked,phSUCCESS,phFAIL);
00341 }
00342 
00343 /* ---------------------------------------------------------------------- */
00344 const char *phNetSource::getHost( )
00345 {
00346     phFUNCTION("phNetSource::getHost")
00347     int locked = 0;
00348     char *retval = NULL;
00349    
00350     phTHIS_LOCK(locked);
00351 
00352     retval = this->m_info->m_host;
00353     
00354     phTHIS_UNLOCK_RET(locked,((const char *)retval),NULL);
00355 }
00356 
00357 /* ---------------------------------------------------------------------- */
00358 int phNetSource::setPort( uint32_t port )
00359 {
00360     phFUNCTION("phNetSource::setPort")
00361     int locked = 0;
00362    
00363     phTHIS_LOCK(locked);
00364 
00365     rc = phNetSource::makePath( this->m_info->m_host,
00366                                 port,
00367                                 this->m_type,
00368                                 &this->m_temp_path);
00369     phCHECK_RC(rc,NULL,"phNetSource::makePath");
00370 
00371     rc = this->setPath(this->m_temp_path);
00372     phCHECK_RC(rc,NULL,"this->setPath(%s)",this->m_temp_path);
00373 
00374     phTHIS_UNLOCK_RET(locked,phSUCCESS,phFAIL);
00375 }
00376 
00377 /* ---------------------------------------------------------------------- */
00378 uint32_t phNetSource::getPort( )
00379 {
00380     phFUNCTION("phNetSource::getPort")
00381     int locked = 0;
00382     uint32_t retval = 0;
00383    
00384     phTHIS_LOCK(locked);
00385 
00386     retval = this->m_info->m_port;
00387     
00388     phTHIS_UNLOCK_RET(locked,retval,0);
00389 }
00390 
00391 /* ---------------------------------------------------------------------- */
00392 int phNetSource::setReconnect( int reconnect )
00393 {
00394     phFUNCTION("phNetSource::setReconnect")
00395     int locked = 0;
00396    
00397     phTHIS_LOCK(locked);
00398 
00399     this->m_reconnect = reconnect;
00400     
00401     phTHIS_UNLOCK_RET(locked,phSUCCESS,phFAIL);
00402 }
00403 
00404 /* ---------------------------------------------------------------------- */
00405 int phNetSource::getReconnect( )
00406 {
00407     phFUNCTION("phNetSource::getReconnect")
00408     int locked = 0;
00409     int retval = 0;
00410    
00411     phTHIS_LOCK(locked);
00412 
00413     retval = this->m_reconnect;
00414     
00415     phTHIS_UNLOCK_RET(locked,retval,0);
00416 }
00417 
00418 /* ---------------------------------------------------------------------- */
00419 int phNetSource::setServerWait( int wait )
00420 {
00421     phFUNCTION("phNetSource::setServerWait")
00422     int locked = 0;
00423    
00424     phTHIS_LOCK(locked);
00425 
00426     this->m_server_wait = wait;
00427     
00428     phTHIS_UNLOCK_RET(locked,phSUCCESS,phFAIL);
00429 }
00430 
00431 /* ---------------------------------------------------------------------- */
00432 int phNetSource::getServerWait( )
00433 {
00434     phFUNCTION("phNetSource::getServerWait")
00435     int locked = 0;
00436     int retval = 0;
00437    
00438     phTHIS_LOCK(locked);
00439 
00440     retval = this->m_server_wait;
00441     
00442     phTHIS_UNLOCK_RET(locked,retval,0);
00443 }
00444 
00445 /* ---------------------------------------------------------------------- */
00446 int phNetSource::setOriginalSize( )
00447 {
00448     phFUNCTION("phNetSource::setOriginalSize")
00449 
00450     rc = this->m_settings_lock.lock();
00451     phPRINT_RC(rc,NULL,"this->m_settings_lock.lock() failed");
00452    
00453     this->m_info->m_do_resize = 0;
00454 
00455     rc = this->m_settings_lock.unlock();
00456     phPRINT_RC(rc,NULL,"this->m_settings_lock.unlock() failed");
00457  
00458     return phSUCCESS;
00459 }
00460 
00461 /* ---------------------------------------------------------------------- */
00462 int phNetSource::setOriginalFormat( )
00463 {
00464     phFUNCTION("phNetSource::setOriginalFormat")
00465 
00466     rc = this->m_settings_lock.lock();
00467     phPRINT_RC(rc,NULL,"this->m_settings_lock.lock() failed");
00468    
00469     this->m_info->m_do_convert = 0;
00470 
00471     rc = this->m_settings_lock.unlock();
00472     phPRINT_RC(rc,NULL,"this->m_settings_lock.unlock() failed");
00473  
00474     return phSUCCESS;
00475 }
00476 
00477 /* ---------------------------------------------------------------------- */
00478 int phNetSource::setOriginal( )
00479 {
00480     phFUNCTION("phNetSource::setOriginal")
00481 
00482     rc = this->m_settings_lock.lock();
00483     phPRINT_RC(rc,NULL,"this->m_settings_lock.lock() failed");
00484    
00485     this->m_info->m_do_convert = 0;
00486     this->m_info->m_do_resize  = 0;
00487 
00488     rc = this->m_settings_lock.unlock();
00489     phPRINT_RC(rc,NULL,"this->m_settings_lock.unlock() failed");
00490  
00491     return phSUCCESS;
00492 }
00493 
00494 /* ---------------------------------------------------------------------- */
00495 int phNetSource::getOriginal(   uint32_t *format, 
00496                                 uint32_t *height,
00497                                 uint32_t *width,
00498                                 uint32_t *size )
00499 {
00500     phFUNCTION("phNetSource::getOriginal")
00501     int locked = 0;
00502    
00503     phMUTEX_LOCK(this->m_orig_lock,locked);
00504 
00505     if (format != NULL)
00506         *format = this->m_orig_format;
00507     if (height != NULL)
00508         *height = this->m_orig_height;
00509     if (width != NULL)
00510         *width = this->m_orig_width;
00511     if (size != NULL)
00512         *size = this->m_orig_size;
00513     
00514     phMUTEX_UNLOCK_RET(this->m_orig_lock,locked,phSUCCESS,phFAIL);
00515 }
00516 
00517 /* ---------------------------------------------------------------------- */
00518 uint32_t phNetSource::getOriginalFormat()
00519 {
00520     phFUNCTION("phNetSource::getOriginalFormat")
00521     int locked = 0;
00522     uint32_t retval = 0;
00523    
00524     phMUTEX_LOCK(this->m_orig_lock,locked);
00525 
00526     retval = this->m_orig_format;
00527     
00528     phMUTEX_UNLOCK_RET(this->m_orig_lock,locked,retval,0);
00529 }
00530 
00531 /* ---------------------------------------------------------------------- */
00532 uint32_t phNetSource::getOriginalHeight()
00533 {
00534     phFUNCTION("phNetSource::getOriginalHeight")
00535     int locked = 0;
00536     uint32_t retval = 0;
00537    
00538     phMUTEX_LOCK(this->m_orig_lock,locked);
00539 
00540     retval = this->m_orig_height;
00541     
00542     phMUTEX_UNLOCK_RET(this->m_orig_lock,locked,retval,0);
00543 }
00544 
00545 /* ---------------------------------------------------------------------- */
00546 uint32_t phNetSource::getOriginalWidth()
00547 {
00548     phFUNCTION("phNetSource::getOriginalWidth")
00549     int locked = 0;
00550     uint32_t retval = 0;
00551    
00552     phMUTEX_LOCK(this->m_orig_lock,locked);
00553 
00554     retval = this->m_orig_width;
00555     
00556     phMUTEX_UNLOCK_RET(this->m_orig_lock,locked,retval,0);
00557 }
00558 
00559 /* ---------------------------------------------------------------------- */
00560 uint32_t phNetSource::getOriginalSize()
00561 {
00562     phFUNCTION("phNetSource::getOriginalSize")
00563     int locked = 0;
00564     uint32_t retval = 0;
00565    
00566     phMUTEX_LOCK(this->m_orig_lock,locked);
00567 
00568     retval = this->m_orig_size;
00569     
00570     phMUTEX_UNLOCK_RET(this->m_orig_lock,locked,retval,0);
00571 }
00572 
00573 /* ---------------------------------------------------------------------- */
00574 const char *phNetSource::getTitle()
00575 {
00576     return (const char *)this->m_info->m_title;
00577 }
00578 
00579 /* ---------------------------------------------------------------------- */
00580 int phNetSource::resetDimensions( )
00581 {
00582     phFUNCTION("phNetSource::resetDimensions")
00583     int locked  = 0;
00584     int mlocked = 0;
00585    
00586     phTHIS_LOCK(locked);
00587     phMUTEX_LOCK(this->m_orig_lock,mlocked);
00588 
00589     rc = this->set( this->m_orig_width,
00590                     this->m_orig_height,
00591                     NULL,-1,-1,-1,-1,-1,-1,
00592                     this->m_orig_format);
00593     phCHECK_RC(rc,NULL,"this->set(%d,%d,NULL,-1,-1,-1,-1,-1,-1,%s)",
00594              this->m_orig_width,this->m_orig_height,
00595              phImageFormatToString(this->m_orig_format));
00596 
00597     phMUTEX_UNLOCK(this->m_orig_lock,mlocked);
00598     phTHIS_UNLOCK(locked);
00599 
00600     return phSUCCESS;
00601 error:
00602     phMUTEX_ERROR_UNLOCK(this->m_orig_lock,mlocked);
00603     phTHIS_ERROR_UNLOCK(locked);
00604 
00605     return phFAIL;
00606 }
00607 
00608 /* ---------------------------------------------------------------------- */
00609 int phNetSource::onApplySettings()
00610 {
00611     phFUNCTION("phNetSource::onApplySettings")
00612     int retrc = phSUCCESS;
00613 
00614     uint32_t i = 0;
00615 
00616     int ch_init = 0;
00617     int ch_b = 0;
00618     int ch_hue = 0;
00619     int ch_color = 0;
00620     int ch_con = 0;
00621     int ch_white = 0;
00622     int ch_channel = 0;
00623     int ch_h = 0;
00624     int ch_w = 0;
00625     int ch_f = 0;
00626     int ch_p = 0;
00627     
00628     ch_init = ph_int32_array_find(this->m_changed_array, phCHANGE_INIT,NULL);
00629     /* 
00630      * this->m_changed_array contains the list of changes that are to 
00631      *  be applied.
00632      *
00633      * This method will call phImageCapture::onApplySettings which will empty
00634      * the array so that settings are applied only once.
00635      */
00636     
00637 #if 0
00638     /* Copy the image settings into the V4L structure */
00639     ch_b = ph_int32_array_find(this->m_changed_array,       phCHANGE_BRIGHTNESS,
00640                             NULL);
00641     ch_hue = ph_int32_array_find(this->m_changed_array,     phCHANGE_HUE,
00642                             NULL);
00643     ch_color = ph_int32_array_find(this->m_changed_array,   phCHANGE_COLOR,
00644                             NULL);
00645     ch_con = ph_int32_array_find(this->m_changed_array,     phCHANGE_CONTRAST,
00646                             NULL);
00647     ch_white = ph_int32_array_find(this->m_changed_array,   phCHANGE_WHITENESS,
00648                             NULL);
00649     if (ch_init > 0) ch_b = ch_hue = ch_color = ch_con = ch_white = 1;
00650     if ((ch_b > 0) || (ch_hue > 0) || (ch_color > 0) || 
00651         (ch_con > 0) || (ch_white > 0))
00652     {
00653     }
00654     
00655     /*--------------------------------------------------------------------*
00656      * From linux/Documentation/video4linux/API.html:
00657      *
00658      * "Each channel can be queries with the VIDIOCGCHAN ioctl call. 
00659      * Before invoking this function the caller must set the channel 
00660      * field to the channel that is being queried. On return the 
00661      * struct video_channel is filled in with information about the 
00662      * nature of the channel itself."
00663      *--------------------------------------------------------------------*/
00664     ch_channel = ph_int32_array_find(this->m_changed_array,phCHANGE_CHANNEL,
00665                                     NULL);
00666     if ((ch_channel > 0) || (ch_init > 0))
00667     {
00668     }
00669     /* else, the channel is < 0 or the current chn # */
00670 #endif
00671     
00672     /* settings that require the capture to not be in progress for the 
00673      * phNetSource settings changes to be applied */
00674     ch_h = ph_int32_array_find(this->m_changed_array, phCHANGE_HEIGHT, NULL);
00675     ch_w = ph_int32_array_find(this->m_changed_array, phCHANGE_WIDTH, NULL);
00676     ch_f = ph_int32_array_find(this->m_changed_array, phCHANGE_FORMAT, NULL);
00677 
00678     /* We need to check the width and height settings before we force them to be
00679      * true.
00680      *
00681      * The image coming from the server can't explicitly have it's size set. 
00682      * 
00683      * Instead we resize the image that is received from the server using the 
00684      * class's width and height settings. 
00685      * 
00686      * If the setSize/setHeight/setWidth method is called, then the image will
00687      * be resized from the original width and height to the new width and 
00688      * height. 
00689      */
00690     if (ch_w || ch_h)
00691     {
00692         phPROGRESS("\n");
00693         this->m_info->m_do_resize = 1;
00694     }
00695     if (ch_f)
00696     {
00697         this->m_info->m_do_convert = 1;
00698     }
00699         
00700     if (ch_init > 0) ch_h = ch_w = ch_f = 1;
00701 
00702     /* update internal information when the path is given */
00703     /* Only do this when the thread isn't running and the stream isn't open */
00704     ch_p = ph_int32_array_find(this->m_changed_array, phCHANGE_PATH, NULL);
00705     /*
00706     i = ph_int32_array_get_length(this->m_changed_array);
00707     phPROGRESS("ch_p:%d ch_init:%d running:%d open:%d length:%u\n",
00708             ch_p,ch_init,this->isRunning(),this->m_is_open,i);
00709     */
00710     /*
00711     if ((ch_init) && (!this->isRunning()))
00712     {
00713         this->m_user_dimensions = 0;
00714     }
00715     */
00716 
00717     /* These checks prevent changing the path while the thread is active */
00718     if (((ch_p > 0) || (ch_init > 0)) && 
00719         ((!(this->isRunning())) && (!(this->m_is_open))))
00720     {
00721         rc = phNetSource::parsePath(this->getPath(),
00722                                     &this->m_info->m_host,
00723                                     &this->m_info->m_port,
00724                                     &this->m_type);
00725         phPRINT_RC(rc,NULL,"phNetSource::parsePath");
00726         retrc = 1;
00727     }
00728 
00729     rc = this->phImageCapture::onApplySettings();
00730     phCHECK_RC(rc,NULL,"this->phImageCapture::onApplySettings() failed.");
00731  
00732     return retrc;
00733 error:
00734 
00735     return phFAIL;
00736 }
00737 
00738 /* ---------------------------------------------------------------------- */
00739 int phNetSource::open(char *path)
00740 {
00741     phFUNCTION("phNetSource::open")
00742     
00743     int locked = 0;
00744 
00745     phTHIS_LOCK(locked);
00746    
00747     /* device is already open, close it */
00748     if (this->isOpen())
00749     {
00750         rc = this->close();
00751         phPRINT_RC(rc,NULL,"this->close()");
00752     }
00753   
00754     if (path != NULL)
00755     {
00756         rc = this->setPath( path );
00757         phPRINT_RC(rc,NULL,"this->setPath( path:%s )",path);
00758     }
00759  
00760     if (!this->isOpen())
00761     {
00762         rc = phNetSource::parsePath(path == NULL ? this->getPath() : path,
00763                                     &this->m_info->m_host,
00764                                     &this->m_info->m_port,
00765                                     &this->m_type);
00766         phPRINT_RC(rc,NULL,"phNetSource::parsePath");
00767                /* Try to apply all the settings to the V4L device */
00768         ph_int32_array_append(this->m_changed_array,phCHANGE_INIT);
00769         this->applySettings();
00770         
00771         this->m_is_open = 1;
00772 
00773         this->connect( false );
00774     }
00775 
00776     phTHIS_UNLOCK(locked);
00777     
00778     return phSUCCESS;
00779 error:
00780     
00781     phTHIS_ERROR_UNLOCK(locked);
00782     
00783     return phFAIL;
00784 }
00785 
00786 /* ---------------------------------------------------------------------- */
00787 int phNetSource::isOpen() 
00788 { 
00789     return ((this->m_is_open > 0) ? 1 : 0); 
00790 }    
00791 
00792 /* ---------------------------------------------------------------------- */
00793 int phNetSource::isConnected() 
00794 { 
00795     phFUNCTION("phNetSource::isConnected")
00796     int locked = 0;
00797     int retrc = 0;
00798 
00799     phTHIS_LOCK(locked);
00800 
00801     if (this->m_info != NULL)
00802     {
00803         if (this->m_connected_type == phNetTypeTCP)
00804         {
00805             if (this->m_info->m_comms->isConnected()) retrc = 1;
00806         }
00807     }
00808     
00809     phTHIS_UNLOCK_RET(locked,retrc,phFAIL);
00810 }    
00811 
00812 
00813 /* ---------------------------------------------------------------------- */
00814 int phNetSource::close()
00815 {
00816     phFUNCTION("phNetSource::close")
00817     int locked = 0;
00818 
00819     phTHIS_LOCK(locked);
00820 
00821     if (this->isRunning())
00822     {
00823         rc = this->stop();
00824         phPRINT_RC(rc,NULL,"this->stop()");
00825     }
00826 
00827     if (this->m_is_open)
00828     {
00829         rc = this->disconnect();
00830         phCHECK_RC(rc,NULL,"this->disconnect");
00831 
00832         this->m_is_open = 0;
00833     }
00834 
00835     phTHIS_UNLOCK_RET(locked,phSUCCESS,phFAIL);
00836 }
00837 
00838 /* ---------------------------------------------------------------------- */
00839 int phNetSource::connect( bool poll )
00840 {
00841     phFUNCTION("phNetSource::connect")
00842     int locked = 0;
00843     int retrc = phSUCCESS;
00844 
00845     phTHIS_LOCK(locked);
00846  
00847     if (this->m_is_open && (!this->isConnected()))
00848     {
00849         if (this->m_type == phNetTypeTCP)
00850         {
00851             this->m_connected_type = phNetTypeTCP;
00852             
00853             if (this->m_info->m_comms != NULL)
00854             {
00855                 phDelete(this->m_info->m_comms);
00856             }
00857             this->m_info->m_comms = new phSocket();
00858             this->m_info->m_comms->setWarningLevel(0);
00859 
00860             rc = this->tcp_connect(this->m_info->m_comms,
00861                                    poll,
00862                                    this->m_info->m_host,
00863                                    this->m_info->m_port,
00864                                    &(this->m_info->m_width),
00865                                    &(this->m_info->m_height),
00866                                    &(this->m_info->m_format),
00867                                    &(this->m_info->m_title)
00868                                    );
00869             retrc = rc;
00870             /*phCHECK_RC(rc,NULL,"this->tcp_connect()");*/
00871         }
00872     }
00873 
00874     phTHIS_UNLOCK_RET(locked,retrc,phFAIL);
00875 }
00876 
00877 /* ---------------------------------------------------------------------- */
00878 int phNetSource::getNextFrame(phImage  *image,
00879                               uint8_t  **image_buf,
00880                               uint32_t *image_size )
00881 {
00882     phFUNCTION("phNetSource::getNextFrame")
00883     int locked = 0;
00884 
00885     phTHIS_LOCK(locked);
00886 
00887     if (this->m_is_open && (this->isConnected()))
00888     {
00889         if (this->m_connected_type == phNetTypeTCP)
00890         {
00891             /* Get the next buffer */
00892             /* Get next frame */
00893             rc = this->tcp_recv(this->m_info->m_comms,
00894                                 image,
00895                                 &this->m_info->m_width,
00896                                 &this->m_info->m_height,
00897                                 &this->m_info->m_format,
00898                                 image_buf,
00899                                 image_size);
00900             phSocket_CHECK_RC(rc,NULL,"this->tcp_recv");
00901         }
00902     }
00903     phTHIS_UNLOCK_RET(locked,phSUCCESS,rc);
00904 }
00905 /* ---------------------------------------------------------------------- */
00906 int phNetSource::disconnect( )
00907 {
00908     phFUNCTION("phNetSource::disconnect")
00909     int locked = 0;
00910     int retrc = phSUCCESS;
00911 
00912     phTHIS_LOCK(locked);
00913  
00914     if (this->m_is_open && (this->isConnected()))
00915     {
00916         if (this->m_connected_type == phNetTypeTCP)
00917         {
00918             rc = this->tcp_disconnect( this->m_info->m_comms );
00919             phCHECK_RC(rc,NULL,"this->tcp_disconnect()");
00920         }
00921 
00922         this->m_connected_type = phNetTypeUNKNOWN;
00923     }
00924 
00925     phTHIS_UNLOCK_RET(locked,retrc,phFAIL);
00926 }
00927 
00928 /* ------------------------------------------------------------------------- */
00929 int phNetSource::tcp_connect( phSocket  *comms,
00930                               bool      poll,
00931                               char      *host,
00932                               uint32_t  port,
00933                               uint32_t  *w,
00934                               uint32_t  *h,
00935                               uint32_t  *f,
00936                               char      **title )
00937 {
00938     phFUNCTION("phNetSource::tcp_connect")
00939     int failrc = phFAIL;
00940   
00941     char *serverTitle = NULL;
00942     
00943     /*
00944     phPROGRESS("Attempting to connect to server - %s:%d\n",
00945              host,port );
00946     */
00947     /* connect to the server */
00948     rc = comms->connect(host, port, poll);
00949     if (!comms->isConnected() || (rc != 0))
00950     {
00951         failrc = rc;
00952         goto error;
00953     }
00954     /*phCHECK_RC(rc,NULL,"Failed to connect to %s\n\n", host);*/
00955     
00956     /*
00957     phPROGRESS("Connected to server (rc:%d connected:%d)- %s:%d\n",
00958              rc,comms->isConnected(),host,port );
00959      */
00960     rc = this->tcp_init(comms,&serverTitle,w,h,f);
00961     phCHECK_RC(rc,NULL,"tcp_init");
00962     
00963     phFree(*title);
00964     
00965     (*title) = (char *)phCalloc(strlen(serverTitle) + 
00966                                 strlen(host) +
00967                                 255,
00968                                 sizeof(char));
00969     phCHECK_NULLPTR(title,"phCalloc","phCalloc failed to allocate title.");
00970 
00971     sprintf((*title),"%s:%d - %s",
00972             host,
00973             port,
00974             serverTitle );
00975     
00976     phFree(serverTitle);
00977 
00978     return phSUCCESS;
00979 error:
00980     phFree(serverTitle);
00981     return failrc;
00982 }
00983 
00984 /* ------------------------------------------------------------------------- */
00985 int phNetSource::tcp_init( phSocket     *comms,
00986                            char         **title, 
00987                            uint32_t     *w, 
00988                            uint32_t     *h, 
00989                            uint32_t     *f )
00990 {
00991     phFUNCTION("phNetSource::tcp_init")
00992 
00993     uint32_t width = 0;
00994     uint32_t height = 0;
00995     uint32_t format = phImageNOFORMAT;
00996     uint32_t titleSize = 0;
00997     uint32_t next_image  = 0xaaaa;
00998     
00999     rc = comms->recv_uint32(&titleSize);
01000     phSocket_CHECK_RC(rc,NULL,"Failed to receive title size\n\n");
01001 
01002     phFree(*title);
01003     
01004     *title = (char *)phMalloc(titleSize+5);
01005     phCHECK_NULLPTR(*title,"phMalloc","phMalloc failed to allocate the title space.");
01006     phMemset(*title,0,titleSize+5);
01007     
01008     rc = comms->recv(*title, titleSize);
01009     DEBUG_PRINT("title:%s\n",*title);
01010     phSocket_CHECK_RC(rc,NULL,"Failed to receive title size\n\n");
01011 
01012     /* receive image dimensions from server */
01013     rc = comms->recv_uint32(&width);
01014     phSocket_CHECK_RC(rc,NULL,"Failed to receive image dimensions(width)\n\n");
01015 
01016     rc = comms->recv_uint32(&height);
01017     phSocket_CHECK_RC(rc,NULL,"Failed to receive image dimensions(height)\n\n");
01018 
01019     rc = comms->recv_uint32(&format);
01020     phSocket_CHECK_RC(rc,NULL,"Failed to receive image format \n\n");
01021     
01022     *w = width;
01023     *h = height;
01024     *f = format;
01025     
01026     return phSUCCESS;
01027     
01028 error:
01029     return rc;
01030 }
01031 
01032 /* ------------------------------------------------------------------------- */
01033 int phNetSource::tcp_recv(  phSocket     *comms,
01034                             phImage      *inputImage,
01035                             uint32_t     *w, 
01036                             uint32_t     *h, 
01037                             uint32_t     *f,
01038                             uint8_t      **data,
01039                             uint32_t     *data_size
01040                           )
01041 {
01042     phFUNCTION("phNetSource::tcp_recv")
01043 
01044     uint32_t    width           = 0;
01045     uint32_t    height          = 0;
01046     uint32_t    format          = (uint32_t)phImageNOFORMAT;
01047     uint32_t    size            = 0;
01048 
01049     phTimeStamp time_start;
01050     phTimeStamp time_stop;
01051     uint32_t    host_send_time  = 0;
01052     int32_t     packet_id       = 0xaaaa;
01053 
01054     time_start.stamp();
01055 
01056     /* receive image dimensions from server */
01057     rc = comms->recv_uint32(&width);
01058     phSocket_CHECK_RC(rc,NULL,"Failed to receive image dimensions(width)\n\n");
01059     //phPRINT("w:%u\n",width);
01060 
01061     rc = comms->recv_uint32(&height);
01062     phSocket_CHECK_RC(rc,NULL,"Failed to receive image dimensions(height)\n\n");
01063     //phPRINT("h:%u\n",height);
01064 
01065     rc = comms->recv_uint32(&format);
01066     phSocket_CHECK_RC(rc,NULL,"Failed to receive image format \n\n");
01067     //phPRINT("f:%u\n",format);
01068 
01069     rc = comms->recv_uint32(&host_send_time);
01070     phCHECK_RC(rc,NULL,"Failed to receive image host_send_time \n\n");
01071     //phPRINT("hst:%d\n",host_send_time);
01072 
01073     /* 0.)  packet_id */
01074     rc = comms->send_int32(packet_id);
01075     phSocket_CHECK_RC(rc,NULL,"Failed to send packet_id image message \n\n");
01076     /* 1.) host_send_time: time the server started sending the data */
01077     rc = comms->send_int32(host_send_time);
01078     phSocket_CHECK_RC(rc,NULL,"Failed to send host_send_time image message \n\n");
01079 
01080     rc = comms->recv_uint32(&size);
01081     phSocket_CHECK_RC(rc,NULL,"Failed to receive image size \n\n");
01082     //phPRINT("s:%u\n",size);
01083 
01084     /* receive a image from the server */
01085     DEBUG_PRINT("receiving image data\n");
01086 
01087     if (size == 0) /* Try to calculate it */
01088     {
01089         size = phIMAGE_SIZE(width,height,format);
01090     }
01091     
01092     /* allocate data if it hasn't been initialized yet */
01093     if (((*data_size) == 0) || (*data == NULL))
01094     {
01095         (*data) = (uint8_t *)phMalloc(size);
01096         phCHECK_NULLPTR(*data,"phMalloc","phMalloc failed to allocate data.");
01097     }
01098     /* reallocate the data if the size changes */
01099     else if (((*data_size) != size) && (*data != NULL))
01100     {
01101         (*data) = (uint8_t *)phRealloc((*data),size);
01102         phCHECK_NULLPTR(*data,"phRealloc","phRealloc failed to allocate data.");
01103     }
01104        
01105     /* Always set this */
01106     *data_size = size;
01107     
01108     /* Get the data from the server */
01109     rc = comms->recv(*data, *data_size);
01110     phSocket_CHECK_RC(rc,NULL,"recv for image data failed.");
01111 
01112     time_stop.stamp();
01113     
01114     /* Send stats back to the server */
01115     /* 2.) */
01116     rc = comms->send_uint32(*data_size);
01117     phSocket_CHECK_RC(rc,NULL,"Failed to send message \n\n");
01118     /* 3.) */
01119     rc = comms->send_uint32(time_start.getMicroseconds());
01120     phSocket_CHECK_RC(rc,NULL,"Failed to send message\n\n");
01121     /* 4.) */
01122     rc = comms->send_uint32(time_stop.getMicroseconds());
01123     phSocket_CHECK_RC(rc,NULL,"Failed to send message\n\n");
01124     
01125 #if 0
01126     phPRINT("0:%8u:%12.lf 1:%8u:%12.lf\n",
01127             time_start.getMicroseconds(),
01128             time_start.getStampValue(),
01129             time_stop.getMicroseconds(),
01130             time_stop.getStampValue());
01131 #endif
01132 #if phNetSource_PRINT_IMAGE_SIZE()
01133     phPROGRESS("format:%s\n",
01134                phImageFormatToString(format));
01135     phPROGRESS("recv:%lu\tactual:%lu\n",
01136                (long unsigned)*data_size,
01137                (long unsigned)phIMAGE_SIZE(width,height,format));
01138 #endif
01139 
01140     /* allocate space for the image */
01141     inputImage->setImage(width,height,format,
01142                         *data_size,
01143                         *data);
01144     
01145     /* keep track */
01146     *w = width;
01147     *h = height;
01148     *f = format;
01149     
01150     return phSUCCESS;
01151 error:
01152     /* might as well... */
01153     phFree(*data);
01154     
01155     *data_size = 0;
01156     
01157     return rc;
01158 }
01159 
01160 /* ------------------------------------------------------------------------- */
01161 int phNetSource::tcp_disconnect( phSocket  *comms )
01162 {
01163     phFUNCTION("phNetSource::tcp_disconnect")
01164   
01165     /* connect to the server */
01166     comms->disconnect();
01167     
01168     return phSUCCESS;
01169 error:
01170     return phFAIL;
01171 }
01172 
01173 /* ---------------------------------------------------------------------- */
01174 int phNetSource::wakeup()
01175 {
01176     phFUNCTION("phNetSource::wakeup")
01177 
01178     if (this->m_info != NULL)
01179     {
01180         if (this->m_info->m_comms != NULL)
01181         {
01182             this->m_info->m_comms->wakeup();
01183         }
01184     }
01185 
01186     rc = phImageCapture::wakeup();
01187     phPRINT_RC(rc,NULL,"phImageCapture::wakeup");
01188 
01189     return phSUCCESS;
01190 }
01191 
01192 /* ---------------------------------------------------------------------- */
01193 int phNetSource::cleanup()
01194 {
01195     phFUNCTION("phNetSource::cleanup")
01196     int locked = 0;
01197    
01198     phTHIS_LOOSE_LOCK(locked);
01199    
01200     rc = this->close();
01201     phPRINT_RC(rc,NULL,"this->close()");
01202     
01203     rc = this->phImageCapture::cleanup();
01204     phPRINT_RC(rc,NULL,"this->phImageCapture::cleanup()");
01205     
01206     phTHIS_LOOSE_UNLOCK(locked);
01207     
01208     return phSUCCESS;
01209 }
01210 
01211 /* ---------------------------------------------------------------------- */
01212 int phNetSource::run()
01213 {
01214     phFUNCTION("phNetSource::run")
01215     int i = 0;
01216     int foo = 0;
01217     int orig_locked = 0;
01218         
01219     /* Returned value from getNextFrame and a loop count */
01220     phImage    *output_buffer   = this->getImage();
01221     
01222     /* local copies of phNetSource object's member vars */
01223     phImage    *image           = new phImage();
01224     uint8_t    *image_buf       = NULL;
01225     uint32_t    image_size      = 0;
01226     int32_t     local_format    = 0;
01227     uint32_t    local_width     = 0;
01228     uint32_t    local_height    = 0;
01229     int         local_do_resize = 0;
01230     int         local_do_convert= 0;
01231 
01232     int         slept               = 0;
01233 #if phNetSource_USE_JITTER_SYNC()
01234     int32_t     sleeptime           = 0;
01235     int32_t     client_jitter_avg   = -1;
01236     int32_t     notify_jitter_avg   = -1;
01237 #endif
01238     
01239     /* Setup */
01240     local_format      = this->m_format;
01241     local_width       = this->m_width;
01242     local_height      = this->m_height;
01243     local_do_resize   = this->m_info->m_do_resize;
01244     local_do_convert  = this->m_info->m_do_convert;
01245    
01246     /* Release the thread that spawned this one */
01247     /* Everything has been copied and everything is ready to start */
01248     rc = this->signal_running();
01249     phPRINT_RC(rc,NULL,"this->signal_running");
01250 
01251     /* if we haven't connected by now and we want to wait, then wait */
01252     while (this->m_server_wait && 
01253            (!this->isConnected()) &&
01254            (this->isRunning()))
01255     {
01256         rc = this->connect( false );
01257         
01258         if ((rc != -5) && (rc < 0)) this->setRunning(0);
01259 
01260         if (!(foo = this->isConnected()))
01261         {
01262             phUSleep(10);
01263             //phYield();
01264         }
01265     }
01266     
01267     DEBUG_PRINT("Thread Started\n");
01268     DEBUG_PRINT("output_buffer: %p\n",output_buffer);
01269     
01270 #if phNetSource_USE_JITTER_SYNC()
01271     /* Reset all the jitter values in the object:
01272        notify, client and client avg*/
01273     rc = output_buffer->resetJitter();
01274     phPRINT_RC(rc,NULL,"output_buffer->resetJitter()");
01275     
01276     /* We want a moving average over 10 samples */
01277     rc = output_buffer->setNotifyJitterAvgSamples(10);
01278     phPRINT_RC(rc,NULL,"output_buffer->setNotifyJitterAvgSamples()");
01279     
01280     /* We want a moving average over 10 samples */
01281     rc = output_buffer->setClientJitterAvgSamples(10);
01282     phPRINT_RC(rc,NULL,"output_buffer->setClientJitterAvgSamples()");
01283 #endif
01284     
01285     while (this->isRunning() && 
01286            (this->isConnected() || (this->m_reconnect)))
01287     {
01288         /* Get the current width/height/format settings to resize the 
01289          * input to for output to connected objects */
01290         rc = this->m_settings_lock.trylock();
01291         phPRINT_RC(rc,NULL,"this->m_settings_lock.trylock();");
01292 
01293         /* only copy the settings if we have exclusize access */
01294         if (rc == phSUCCESS)
01295         {
01296             local_do_resize   = this->m_info->m_do_resize;
01297             local_do_convert  = this->m_info->m_do_convert;
01298             local_width       = this->m_width;
01299             local_height      = this->m_height;
01300             local_format      = this->m_format;
01301 
01302             rc = this->m_settings_lock.unlock();
01303             phPRINT_RC(rc,NULL,"this->m_settings_lock.unlock()");
01304         }
01305                 
01306         if (!this->isConnected())
01307         {
01308             if (this->m_reconnect)
01309             {
01310                 rc = this->connect(false);
01311 
01312                 if (!this->isConnected())
01313                 {
01314                     phUSleep(10);
01315                     //phYield();
01316                 }
01317                 
01318                 continue;
01319             }
01320             else 
01321             {
01322                 continue;
01323             }
01324         }
01325         
01326         if (!this->isRunning()) 
01327         {
01328             continue;
01329         }
01330 
01331         rc = this->getNextFrame(image,&image_buf,&image_size);
01332         phPRINT_RC(rc,NULL,"this->recv()");
01333 
01334         /* If the recv failed, then disconnect;
01335          * this->m_reconnect above will try to reconnect*/
01336         if (rc < 0)
01337         {
01338             this->disconnect();
01339             continue;
01340         }
01341         
01342         /* If there's an error, then go to the beginning
01343          * of the loop. There's a potential we can reset ourselves */
01344         if (rc != phSUCCESS) continue;
01345 
01346         /* Convert to the output format */
01347         /* Setup the image according to desired output format */
01348         if (local_do_resize)
01349         {
01350             rc = image->resize(local_width,local_height);
01351             phPRINT_RC(rc,NULL,"image->resize(%d,%d)",
01352                     local_width,local_height);
01353         }
01354         if (local_do_convert)
01355         {
01356             rc = image->convert(local_format);
01357             phPRINT_RC(rc,NULL,"image->convert(%s)",
01358                        phImageFormatToString(local_format));
01359         }
01360         
01361         /* if (output_buffer->tryWritelock() == 0) */
01362         if (output_buffer->writeLock() == 0)
01363         {
01364             rc = output_buffer->swapImage(*image);
01365             phCHECK_RC(rc,NULL,"output_buffer->swapImage(*image)");
01366      
01367             /* Save the current frame's original settings */
01368             phMUTEX_LOOSE_LOCK(this->m_orig_lock,orig_locked);
01369             /* \/ ORIGINAL CODE \/ */
01370             this->m_orig_width  = this->m_info->m_width;
01371             this->m_orig_height = this->m_info->m_height;
01372             this->m_orig_format = this->m_info->m_format;
01373             this->m_orig_size   = image_size;
01374             phMUTEX_LOOSE_UNLOCK(this->m_orig_lock,orig_locked);
01375        
01376 #if phNetSource_USE_JITTER_SYNC()
01377             client_jitter_avg = output_buffer->getClientJitterAvg();
01378             notify_jitter_avg = output_buffer->getNotifyJitterAvg();
01379 #endif
01380         
01381             output_buffer->rwUnlock();
01382 
01383 #if phNetSource_USE_JITTER_SYNC()
01384 #if VERBOSE()
01385             /*phPROGRESS("(%p) <---\n",output_buffer);*/
01386             phPRINT("(%s) client:%ld notify:%ld\n",
01387                             function,
01388                             client_jitter_avg,
01389                             notify_jitter_avg);
01390 #endif
01391             /* We check to see if the client jitter is greater than the notify
01392              * jitter so we slow down the sending of images from the other side
01393              * to synch. up with how fast images are being processed on this
01394              * side */
01395             if (notify_jitter_avg < client_jitter_avg)
01396             {
01397                 sleeptime = (client_jitter_avg - notify_jitter_avg);
01398 #if VERBOSE()
01399                 phPRINT("(%s)sleeptime:%ld client:%d notify:%d\n",
01400                             function,
01401                             sleeptime,
01402                             client_jitter_avg,
01403                             notify_jitter_avg);
01404 #endif           
01405                 slept = 1;
01406                 phUSleep(sleeptime);
01407             }
01408 #endif
01409         }
01410         if (!slept)
01411         {
01412             if (1)
01413             {
01414                 phUSleep(0);
01415             }
01416             else
01417             {
01418                 phYield();
01419             }
01420         }
01421         slept = 0;
01422     }
01423         
01424     phDelete(image);
01425     phFree(image_buf);
01426     image_size = 0;
01427     
01428     DEBUG_PRINT("Thread returning cleanly\n");
01429    
01430     return phSUCCESS;
01431     
01432 error:
01433     phPROGRESS("Thread returning with error\n");
01434     
01435     phDelete(image);
01436     phFree(image_buf);
01437     image_size = 0;
01438 
01439     rc = this->signal_error();
01440     phPRINT_RC(rc,NULL,"this->signal_error");
01441     
01442     return phFAIL;
01443 }
01444 




Copyright (C) 2002 - 2007 Philip D.S. Thoren ( pthoren@users.sourceforge.net )
University Of Massachusetts at Lowell
Robotics Lab
SourceForge.net Logo

Generated on Sat Jun 16 02:44:03 2007 for phission by  doxygen 1.4.4