VideoManager.cpp
Go to the documentation of this file.
00001 #include <math.h>
00002 #include <assert.h>
00003 #include <sys/time.h>
00004 #include "canon_vbc50i/libCanon/VideoManager.h"
00005 #include "canon_vbc50i/libCanon/JpegReader.h"
00006 #ifdef USE_IPP
00007 #include "canon_vbc50i/libCanon/JpegReader-ipp.h"
00008 #endif
00009 
00010 VideoManager::VideoManager()
00011 {
00012 #ifdef USE_IPP
00013         jpeg = new JpegReaderIPP;
00014 #else
00015         jpeg = new JpegReader;
00016 #endif
00017 
00018         observedFrameRate = 0;
00019         lastFrameTimeStamp = -1;
00020         interImageDelay = 0;
00021         paused = true;
00022         readyToRequest = false;
00023         verbose = 1;
00024         signal = NULL;
00025         signalarg = NULL;
00026         videosock = NULL;
00027 
00028         destination = NULL;
00029         frame = 0;
00030         terminate = false;
00031         savestream = false;
00032 
00033         rec_thr_id = 0;
00034         req_thr_id = 0;
00035         pthread_mutex_init(&sockMtx,NULL);
00036         pthread_mutex_init(&initMtx,NULL);
00037         pthread_mutex_init(&reqMtx,NULL);
00038         pthread_cond_init(&reqCond,NULL);
00039 
00040 }
00041 
00042 VideoManager::~VideoManager()
00043 {
00044         //printf("~VideoManager\n");
00045         close();
00046         delete jpeg;
00047         jpeg = NULL;
00048 }
00049 
00050 void VideoManager::setVerboseLevel(unsigned int v) {
00051         verbose=v;
00052         if (videosock != NULL) {
00053                 if (verbose) 
00054                         videosock->showErrors(); 
00055                 else 
00056                         videosock->hideErrors();
00057         }
00058         if (verbose > 1)
00059                 printf("VideoManager: Setting verbose level to %d\n",verbose);
00060 }
00061 
00062 
00063 double ts() {
00064         struct timeval tv;
00065         gettimeofday(&tv,NULL);
00066         return tv.tv_sec + tv.tv_usec*1e-6;
00067 }
00068 
00069 bool VideoManager::receiveOneFrame()
00070 {
00071         pthread_mutex_lock(&initMtx);
00072         pthread_mutex_unlock(&initMtx);
00073         if (videosock == NULL) goto clean_exit;
00074         // will be dealt with in request thread
00075         if (videosock->IsBroken()) goto clean_exit; 
00076         if (!videosock->IsOpen()) goto clean_exit;
00077         //printf("Waiting for one frame\n");    
00078         while (1) {
00079                 if (!reception.receive(videosock,5000))
00080                         goto clean_exit;
00081                 //printf("Received videogram %02X\n",reception.getId());        
00082                 switch (reception.getId()) {
00083                         case 0x02:
00084                                 observedFrameRate = 1.0 / 
00085                                         (reception.getTimeStamp() - lastFrameTimeStamp);
00086                                 lastFrameTimeStamp = reception.getTimeStamp();
00087                                 readyToRequest = true;
00088                                 pthread_cond_broadcast(&reqCond);
00089                                 decodeImage(); 
00090                                 return true;
00091                         default : 
00092                                 if (verbose >= 1) {
00093                                         printf("Discarding: ");reception.print();
00094                                 }
00095                                 break;
00096                 }
00097         }
00098 clean_exit:
00099         //printf("Videogram reception failed\n");       
00100         readyToRequest = true;
00101         pthread_cond_broadcast(&reqCond);
00102         return false;
00103 }
00104 
00105 bool VideoManager::decodeImage()
00106 {
00107 #ifdef DOTIMING
00108         static double stopclock = 0;
00109         static double lasttime = -1;
00110         struct timeval tv;
00111         double t0,t1;
00112         gettimeofday(&tv,NULL);t0=tv.tv_sec+tv.tv_usec*1e-6;
00113         if (lasttime < 0) lasttime = t0; 
00114 #endif
00115         frame += 1;
00116 
00117         if (destination != NULL) {
00118                 jpeg->setExternalOutput(destination);
00119         }
00120         bool res = jpeg->load(reception.getData(),reception.getLength());
00121         jpeg->setTimeStamp(reception.getTimeStamp());
00122 
00123 #ifdef DOTIMING
00124         gettimeofday(&tv,NULL);t1=tv.tv_sec+tv.tv_usec*1e-6;
00125         stopclock += t1-t0;
00126 
00127         if (frame % 10 == 0) {
00128                 printf("\nDecode: %f s\n",1e3*stopclock/10);
00129                 printf("FPS: %f 10 in %f\n",10/(t1-lasttime),(t1-lasttime) );
00130                 stopclock = 0;
00131                 lasttime = -1;
00132         }
00133 #endif
00134 
00135         if (!res) 
00136                 return false;
00137         if (savestream) 
00138                 ssaver.record((const char*)reception.getData(),reception.getLength());
00139         if (signal != NULL) {
00140                 signal(signalarg,jpeg,frame);
00141         }
00142         return true;
00143 }
00144 
00145 void * video_reception_thread(void * thrarg)
00146 {
00147         unsigned int nfailure = 0;
00148         VideoManager * vm = (VideoManager*)thrarg;
00149         while (!vm->terminate) {
00150                 if (vm->isPaused()) {
00151                         // wait 5 ms;
00152                         usleep(5000);
00153                 } else if (vm->receiveOneFrame()) {
00154                         nfailure = 0;
00155                 } else {
00156                         switch (vm->verbose) {
00157                                 case 2:
00158                                         printf("Failed to receive videogram (%d)\n",nfailure);
00159                                         break;
00160                                 case 1:
00161                                         printf("?");fflush(stdout);
00162                                         break;
00163                                 default :
00164                                         break;
00165                         }
00166                         nfailure += 1;
00167                 }
00168                 if (vm->verbose>1) {
00169                         printf("%c",vm->terminate?'!':'.');
00170                         fflush(stdout);
00171                 }
00172         }
00173         return NULL;
00174 }
00175 
00176 void * video_request_thread(void * thrarg)
00177 {
00178         VideoManager * vm = (VideoManager*)thrarg;
00179         while (!vm->terminate) {
00180                 if (vm->checkSocketState()) {
00181                         vm->requestNextImageIfNecessary();
00182                 } else {
00183                         sleep(1);
00184                 }
00185         }
00186         return NULL;
00187 }
00188 
00189 bool VideoManager::checkSocketState()
00190 {
00191         if (videosock->IsBroken()) {
00192                 printf("VM: Socket is broken, trying to reconnect\n");
00193                 return reconnect();
00194         }
00195         return true;
00196 }
00197 
00198 bool VideoManager::requestNextImageIfNecessary()
00199 {
00200         if (paused) {
00201                 usleep(5000);
00202                 return false;
00203         }
00204         if (!readyToRequest) {
00205                 pthread_cond_wait(&reqCond,&reqMtx);
00206         }
00207         
00208         double now = ts();
00209         if ((now - lastFrameTimeStamp) >= interImageDelay) {
00210                 readyToRequest = false;
00211                 return requestNextImage();
00212         } else {
00213                 double sleeptime = interImageDelay - (now - lastFrameTimeStamp);
00214                 usleep((unsigned int)(sleeptime*1e6));
00215         }
00216 
00217         return false;
00218 }
00219 
00220 
00221 bool VideoManager::open(const char *  hostname, unsigned int port)
00222 {
00223         pthread_mutex_init(&initMtx,NULL);
00224         pthread_mutex_lock(&initMtx);
00225         if (videosock != NULL) close();
00226         frame = 0;
00227 
00228         //printf("Connecting to %s:%d\n",hostname,port);
00229         videosock = new Socket(hostname,port);
00230         if (verbose) 
00231                 videosock->showErrors(); 
00232         else 
00233                 videosock->hideErrors();
00234         if (!videosock->Open()) {
00235                 delete videosock;
00236                 videosock = NULL;
00237                 return false;
00238         }
00239         if (verbose>=1)
00240                 printf("Successfully connected to %s:%d\n",hostname,port);
00241 
00242         if (verbose==0)
00243                 videosock->hideErrors();
00244 
00245         terminate = false; paused = false;
00246         pthread_create(&rec_thr_id,NULL,video_reception_thread,this);
00247         if (!sendInitSeq()) return false;
00248 
00249         readyToRequest = true;
00250         pthread_create(&req_thr_id,NULL,video_request_thread,this);
00251         pthread_mutex_unlock(&initMtx);
00252         return true;
00253 }
00254 
00255 bool VideoManager::reconnect()
00256 {
00257         pthread_mutex_init(&initMtx,NULL);
00258         pthread_mutex_lock(&initMtx);
00259         if (verbose > 0)
00260                 printf("VM: reconnecting\n");
00261         videosock->Close();
00262         sleep(1);
00263         if (!videosock->Open()) {
00264                 if (verbose > 0)
00265                         printf("VM: Failed to reopen connection\n");
00266                 return false;
00267         }
00268         if (!sendInitSeq()) {
00269                 if (verbose > 0)
00270                         printf("VM: Failed to resend init seq\n");
00271                 return false;
00272         }
00273         if (!setImageSize(width,height)) {
00274                 if (verbose > 0)
00275                         printf("VM: Failed to reset image size\n");
00276                 return false;
00277         }
00278         pthread_mutex_unlock(&initMtx);
00279         return true;
00280 }
00281 
00282 bool VideoManager::close()
00283 {
00284         terminate = true;
00285         pthread_mutex_unlock(&initMtx);
00286         if (rec_thr_id != 0) {
00287                 pthread_join(rec_thr_id,NULL);
00288                 rec_thr_id = 0;
00289         }
00290         if (req_thr_id != 0) {
00291                 pthread_cancel(req_thr_id);
00292                 req_thr_id = 0;
00293         }
00294         if (videosock != NULL) {
00295                 videosock->Close();
00296                 delete videosock;
00297                 videosock = NULL;
00298         }
00299         paused = true;
00300         return true;
00301 }
00302 
00303 bool VideoManager::requestNextImage()
00304 {
00305         if (videosock == NULL) return false;
00306         if (videosock->IsBroken()) return false;
00307         if (!videosock->IsOpen()) return false;
00308 
00309         VideoGram vg(0x85);
00310         pthread_mutex_lock(&sockMtx);
00311         bool res = vg.send(videosock);
00312         pthread_mutex_unlock(&sockMtx);
00313         //printf("Requested new image: %s\n",res?"Success":"Failure");
00314         return res;
00315 }
00316 
00317 bool VideoManager::getImageSize(unsigned int *width, unsigned int *height)
00318 {
00319         *width = jpeg->width;
00320         *height = jpeg->height;
00321         return true;
00322 }
00323 
00324 
00325 bool VideoManager::setImageSize(unsigned int _width, unsigned int _height)
00326 {
00327         unsigned char message[4] = {
00328                 0x00, 0x00, 0x00, 0x00
00329         };
00330         bool known_size = false;
00331         // Pedantic function to check for input values
00332         if ((_width==768) && (_height==576)) known_size = true;
00333         if ((_width==384) && (_height==288)) known_size = true;
00334         if ((_width==192) && (_height==144)) known_size = true;
00335         if ((_width==96) && (_height==72)) known_size = true;
00336         if (!known_size) {
00337                 fprintf(stderr,"Warning unknown image size %dx%d\n",
00338                                 _width,_height);
00339                 assert(known_size);
00340         }
00341         width = _width;
00342         height = _height;
00343         message[0] = width >> 8;
00344         message[1] = width & 0xFF;
00345         message[2] = height >> 8;
00346         message[3] = height & 0xFF;
00347         VideoGram vg(0x88);
00348         vg.setData(message,4);
00349         pthread_mutex_lock(&sockMtx);
00350         bool res = vg.send(videosock);
00351         pthread_mutex_unlock(&sockMtx);
00352         if (verbose > 0) {
00353                 printf("Sent: ");vg.print();
00354                 printf("Changed image size: %s\n",res?"Success":"Failure");
00355         }
00356         return res;
00357 }
00358 
00359 
00360 static void waitZeroAndPrint(Socket * sock,unsigned int verbose=0)
00361 {
00362         bool printed = false;
00363         while (sock->WaitData(100)) {
00364                 unsigned char c;
00365                 sock->Receive(&c,1);
00366                 if (verbose >= 1) {
00367                         printed = true;
00368                         if (isprint(c)) 
00369                                 fprintf(stdout,"%c",c);
00370                         else 
00371                                 fprintf(stdout,".");
00372                 }
00373                 //fprintf(stdout," 0r%02X ",c); 
00374                 if (c == 0) break;
00375         }
00376         if (printed) fprintf(stdout,"\n");
00377 }
00378 
00379 
00380 static bool send0x0A(Socket * sock, unsigned char * s)
00381 {
00382         unsigned int l = strlen((char*)s);
00383         s[l] = 0x0a;
00384         s[l+1] = 0x00;
00385         bool res = sock->SendAll(s,l+1,100);    
00386         //printf("Sent: '%s': %d\n",s,res);
00387                         
00388         return res;
00389 }
00390 
00391 bool VideoManager::sendInitSeq()
00392 {
00393         if (videosock == NULL) {
00394                 printf("sendInitSeq: videosock == NULL\n");
00395                 return false;
00396         }
00397         if (!videosock->IsOpen()) {
00398                 printf("sendInitSeq: videosock not open\n");
00399                 return false;
00400         }
00401         unsigned char tmp[1024];
00402         strcpy((char*)tmp,"VERSION"); 
00403         if (!send0x0A(videosock,tmp)) return false;
00404         waitZeroAndPrint(videosock,verbose);
00405         //printf("\n---\n\n");
00406 
00407         unsigned char login[20] = {
00408                 'S', 'U', 'P', 'E', 'R', ' ', 'r', 0x10,
00409                 0x10, 0x0b, 0x45, 0x29, 0x3d, 0x52, 0x3c, 0x4a,
00410                 0x4f, 0x16, 0x00
00411         };
00412         if (!send0x0A(videosock,login)) return false;
00413         unsigned char admin[] = "SET Mode Administrator";
00414         if (!send0x0A(videosock,admin)) return false;
00415         unsigned char muxconf[] = "GET MUXCONF";
00416         if (!send0x0A(videosock,muxconf)) return false;
00417         waitZeroAndPrint(videosock,verbose);
00418         //printf("\n---\n\n");
00419         unsigned char start[] = "START";
00420         if (!send0x0A(videosock,start)) return false;
00421 
00422         VideoGram vg;
00423         reception.receive(videosock,100);
00424         if (verbose >= 2) {
00425                 printf("Sent    : START\n");
00426                 printf("Received: ");reception.print();
00427         }
00428 
00429         vg.reset(); vg.setId(0x85); 
00430         if (!vg.send(videosock)) return false;
00431         reception.receive(videosock,100);
00432         if (verbose >= 2) {
00433                 printf("Sent    : ");vg.print();
00434                 printf("Received: ");reception.print();
00435         }
00436 
00437         unsigned char data8c[4] = {0x03, 0x0a, 0x0b, 0x0e};
00438         vg.reset(); vg.setId(0x8c);  vg.setData(data8c,4);
00439         if (!vg.send(videosock)) return false;
00440         reception.receive(videosock,100);
00441         if (verbose >= 2) {
00442                 printf("Sent    : ");vg.print();
00443                 printf("Received: ");reception.print();
00444         }
00445 
00446         vg.reset(); vg.setId(0x8d); 
00447         if (!vg.send(videosock)) return false;
00448         reception.receive(videosock,100);
00449         if (verbose >= 2) {
00450                 printf("Sent    : ");vg.print();
00451                 printf("Received: ");reception.print();
00452         }
00453 
00454         vg.reset(); vg.setId(0x87); 
00455         if (!vg.send(videosock)) return false;
00456         reception.receive(videosock,100);
00457         if (verbose >= 2) {
00458                 printf("Sent    : ");vg.print();
00459                 printf("Received: ");reception.print();
00460         }
00461 
00462         unsigned char data91[4] = {0x00, 0x00, 0x00, 0x00};
00463         vg.reset(); vg.setId(0x91); vg.setData(data91,4); 
00464         if (!vg.send(videosock)) return false;
00465         reception.receive(videosock,100);
00466         if (verbose >= 2) {
00467                 printf("Sent    : ");vg.print();
00468                 printf("Received: ");reception.print();
00469         }
00470 
00471         if (verbose >= 1)
00472                 printf("Video initialization completed\n");
00473         return true;
00474 }
00475 
00476 bool VideoManager::pause()
00477 {
00478         paused = true;
00479         return true;
00480 }
00481 
00482 bool VideoManager::resume()
00483 {
00484         paused = false;
00485         requestNextImage();
00486         return true;
00487 }
00488 
00489 void VideoManager::setMaxFrameRate()
00490 {
00491         interImageDelay = 0;
00492 }
00493 
00494 void VideoManager::setFrameRate(double fps)
00495 {
00496         if (fps < 0) return;
00497         if (isinf(fps))  {
00498                 interImageDelay = 0;
00499         } else {
00500                 interImageDelay = 1.0/fps;
00501                 if (interImageDelay > 0.005) {
00502                         // 5 millisecond for the communication
00503                         interImageDelay -= 0.005;
00504                 }
00505         }
00506 }
00507 
00508 double VideoManager::getRequiredFrameRate()
00509 {
00510         if (interImageDelay == 0) 
00511                 return INFINITY;
00512         return 1.0/(interImageDelay+0.01);
00513 }
00514 
00515 double VideoManager::getObservedFrameRate()
00516 {
00517         return observedFrameRate;
00518 }
00519 
00520 
00521 void VideoManager::setVideoOutputColorSpace(JpegReader::ColorSpace cspace)
00522 {
00523         jpeg->setOutputColorSpace(cspace);
00524 }
00525 
00526 void VideoManager::setRecordingDestination(const char * dirname)
00527 {
00528         ssaver.setDirectory(dirname);
00529 }
00530 
00531 void VideoManager::setRecordingBasename(const char * bname)
00532 {
00533         ssaver.setBase(bname);
00534 }
00535 


canon_vbc50i
Author(s): Cedric Pradalier
autogenerated on Sun Oct 5 2014 23:47:45