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
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
00075 if (videosock->IsBroken()) goto clean_exit;
00076 if (!videosock->IsOpen()) goto clean_exit;
00077
00078 while (1) {
00079 if (!reception.receive(videosock,5000))
00080 goto clean_exit;
00081
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
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
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
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
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
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
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
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
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
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
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