00001 #include "Daemon.h"
00002 #include <linux/videodev2.h>
00003
00004 #include "linux/mt9p031.h"
00005
00006 #warning Do not forget to update the mt9p031.h header when changing the kernel!
00007
00008 #include "../Time.h"
00009 #include "../Action.h"
00010
00011 #include <errno.h>
00012 #include <sys/types.h>
00013 #include <sys/stat.h>
00014 #include <sys/fcntl.h>
00015 #include <sys/ioctl.h>
00016 #include <poll.h>
00017 #include <string.h>
00018
00019
00020 #ifdef DEBUG
00021 #define dprintf(...) printf(__VA__ARGS__)
00022 #else
00023 #define dprintf(...)
00024 #endif
00025
00026 namespace FCam { namespace F2 {
00027
00028 void *daemon_setter_thread_(void *arg) {
00029 Daemon *d = (Daemon *)arg;
00030 d->runSetter();
00031 d->setterRunning = false;
00032 pthread_exit(NULL);
00033 }
00034
00035 void *daemon_handler_thread_(void *arg) {
00036 Daemon *d = (Daemon *)arg;
00037 d->runHandler();
00038 d->handlerRunning = false;
00039 pthread_exit(NULL);
00040 }
00041
00042 void *daemon_action_thread_(void *arg) {
00043 Daemon *d = (Daemon *)arg;
00044 d->runAction();
00045 d->actionRunning = false;
00046 pthread_exit(NULL);
00047 }
00048
00049 Daemon::Daemon() :
00050 stop(false),
00051 generator(NULL),
00052 frameLimit(128),
00053 dropPolicy(FCam::Sensor::DropNewest),
00054 setterRunning(false),
00055 handlerRunning(false),
00056 actionRunning(false),
00057 waitingForFirstRequest(true),
00058 debugMode(false) {
00059
00060
00061 current.f2Request = new Shot;
00062
00063
00064 sensor = V4L2Sensor::instance("/dev/video0");
00065
00066
00067
00068
00069 if (getuid()) {
00070 printf("Camera Daemon can only run as root. Aborting.\n");
00071 return;
00072 }
00073
00074
00075 FILE *f = fopen("/proc/sys/kernel/sched_rt_runtime_us", "w");
00076 if (f) {
00077 fprintf(f, "-1");
00078 fclose(f);
00079 } else {
00080 printf("Could not enable real-time scheduling modes, daemon thread creating may fail\n");
00081 }
00082
00083
00084 if ((errno =
00085 -(pthread_mutex_init(&requestQueueMutex, NULL) ||
00086 pthread_mutex_init(&frameQueueMutex, NULL) ||
00087 pthread_mutex_init(&actionQueueMutex, NULL) ||
00088 pthread_mutex_init(&inFlightQueueMutex, NULL) ||
00089 pthread_mutex_init(&cameraMutex, NULL)))) {
00090 perror("Error creating mutexes");
00091 }
00092
00093
00094 sem_init(&frameQueueSemaphore, 0, 0);
00095 sem_init(&actionQueueSemaphore, 0, 0);
00096
00097
00098 pipelineFlush = true;
00099
00100 }
00101
00102 void Daemon::launchThreads() {
00103
00104 pthread_attr_t attr;
00105 struct sched_param param;
00106
00107
00108
00109 param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
00110
00111 pthread_attr_init(&attr);
00112
00113 if ((errno =
00114 -(pthread_attr_setschedparam(&attr, ¶m) ||
00115 pthread_attr_setschedpolicy(&attr, SCHED_FIFO) ||
00116 pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) ||
00117 pthread_create(&setterThread, &attr, daemon_setter_thread_, this)))) {
00118 perror("Error creating daemon setter thread");
00119 return;
00120 } else {
00121 setterRunning = true;
00122 }
00123
00124
00125 param.sched_priority = sched_get_priority_min(SCHED_FIFO);
00126
00127 if ((errno =
00128 -(pthread_attr_setschedparam(&attr, ¶m) ||
00129 pthread_attr_setschedpolicy(&attr, SCHED_FIFO) ||
00130 pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) ||
00131 pthread_create(&handlerThread, &attr, daemon_handler_thread_, this)))) {
00132 perror("Error creating daemon handler thread");
00133 return;
00134 } else {
00135 handlerRunning = true;
00136 }
00137
00138
00139 param.sched_priority = sched_get_priority_max(SCHED_FIFO);
00140
00141 if ((errno =
00142 -(pthread_attr_setschedparam(&attr, ¶m) ||
00143 pthread_attr_setschedpolicy(&attr, SCHED_FIFO) ||
00144 pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) ||
00145 pthread_create(&actionThread, &attr, daemon_action_thread_, this)))) {
00146 perror("Error creating daemon action thread");
00147 return;
00148 } else {
00149 actionRunning = true;
00150 }
00151
00152 pthread_attr_destroy(&attr);
00153 }
00154
00155 Daemon::~Daemon() {
00156 stop = true;
00157
00158
00159 sem_post(&actionQueueSemaphore);
00160
00161 if (setterRunning)
00162 pthread_join(setterThread, NULL);
00163
00164 if (handlerRunning)
00165 pthread_join(handlerThread, NULL);
00166
00167 if (actionRunning)
00168 pthread_join(actionThread, NULL);
00169
00170 pthread_mutex_destroy(&requestQueueMutex);
00171 pthread_mutex_destroy(&frameQueueMutex);
00172 pthread_mutex_destroy(&inFlightQueueMutex);
00173 pthread_mutex_destroy(&actionQueueMutex);
00174
00175 sensor->close();
00176 }
00177
00178
00179 void Daemon::setRequestGenerator(Daemon::RequestGenerator *gen) {
00180 generator = gen;
00181 if (waitingForFirstRequest) {
00182
00183 printf("Calling generator for the first time\n");
00184 generator->generateRequest();
00185 }
00186 }
00187
00188 Daemon::RequestGenerator *Daemon::getRequestGenerator() {
00189 return generator;
00190 }
00191
00192
00193 int Daemon::requestFrame(Frame *req) {
00194
00195 pthread_mutex_lock(&requestQueueMutex);
00196 requestQueue.push(req);
00197 pthread_mutex_unlock(&requestQueueMutex);
00198
00199 if (waitingForFirstRequest) {
00200 printf("First frame requested\n");
00201
00202 waitingForFirstRequest = false;
00203 launchThreads();
00204 }
00205 return 0;
00206 }
00207
00208 Frame *Daemon::getNextFrame() {
00209
00210 sem_wait(&frameQueueSemaphore);
00211 pthread_mutex_lock(&frameQueueMutex);
00212 Frame *f = frameQueue.front();
00213 frameQueue.pop();
00214 pthread_mutex_unlock(&frameQueueMutex);
00215 return f;
00216 }
00217
00218 void Daemon::setDropPolicy(FCam::Sensor::DropPolicy p, int f) {
00219 dropPolicy = p;
00220 frameLimit = f;
00221 enforceDropPolicy();
00222 }
00223
00224 void Daemon::enforceDropPolicy() {
00225 if (frameQueue.size() > frameLimit) {
00226 pthread_mutex_lock(&frameQueueMutex);
00227 int drops = frameQueue.size() - frameLimit;
00228 if (drops > 0) {
00229 printf("WARNING: frame limit hit (%d), silently dropping %d frames.\n"
00230 "You're not draining the frame queue quickly enough. Use longer \n"
00231 "frame times or drain the frame queue until empty every time you \n"
00232 "call getFrame()\n", frameLimit, drops);
00233 if (dropPolicy == FCam::Sensor::DropOldest) {
00234 for (int i = 0; i < drops; i++) {
00235 sem_wait(&frameQueueSemaphore);
00236 delete frameQueue.front();
00237 frameQueue.pop();
00238 }
00239 } else if (dropPolicy == FCam::Sensor::DropNewest) {
00240
00241 for (size_t i = 0; i < frameQueue.size() - drops; i++) {
00242 frameQueue.push(frameQueue.front());
00243 frameQueue.pop();
00244 }
00245 for (int i = 0; i < drops; i++) {
00246 sem_wait(&frameQueueSemaphore);
00247 delete frameQueue.front();
00248 frameQueue.pop();
00249 }
00250 } else {
00251 printf("Unknown drop policy! Not dropping frames.\n");
00252 }
00253 }
00254 pthread_mutex_unlock(&frameQueueMutex);
00255 }
00256 }
00257
00258 void Daemon::debugTiming(bool enable) {
00259 debugMode = enable;
00260 }
00261
00262 void Daemon::runSetter() {
00263
00264
00265
00266 tickSetter(Time::now());
00267 while (!stop) {
00268
00269 int err;
00270 timeval hs_vs_stamp;
00271 v4l2_control ctrl;
00272 ctrl.id = MT9P031_CID_WAIT_HSVS_1;
00273 ctrl.value = 0;
00274
00275 int currentFD = sensor->getFD();
00276
00277 Time now = Time::now();
00278
00279
00280
00281 if (ioctl(currentFD, VIDIOC_G_CTRL, &ctrl) != 0) {
00282 printf("HSVS error\n");
00283 } else {
00284 if (ctrl.value == -1) {
00285 printf("HSVS waiting timeout (probably)\n");
00286 hs_vs_stamp.tv_sec = now.s();
00287 hs_vs_stamp.tv_usec = now.us();
00288 } else {
00289
00290 hs_vs_stamp.tv_sec = ctrl.value;
00291
00292 ctrl.id = MT9P031_CID_WAIT_HSVS_2;
00293 err = ioctl(currentFD, VIDIOC_G_CTRL, &ctrl);
00294 if (err != 0) {
00295 perror ("Error reading HSVS_2");
00296 } else {
00297 hs_vs_stamp.tv_usec = ctrl.value;
00298 }
00299 }
00300
00301
00302 tickSetter(Time(hs_vs_stamp));
00303 }
00304 }
00305
00306 }
00307
00308 void Daemon::setReadoutParams(Frame *req, bool modeSwitch) {
00309
00310 bool updatedParameters = false;
00311
00312
00313 if (updatedParameters)
00314 sensor->setControl(MT9P031_CID_WRITE_PARAMS, 0);
00315
00316 }
00317
00318 void Daemon::setTimes(Frame *req, const Time &hs_vs, bool modeSwitch) {
00319
00320 static int lastReadout = 0;
00321 static bool firstFrame = true;
00322 int modeSwitchLag;
00323
00324 if (req) {
00325 if (firstFrame) {
00326 modeSwitchLag = req->frameTime;
00327 firstFrame = false;
00328 } else {
00329 modeSwitchLag = modeSwitch ? 20000 + req->frameTime : 0;
00330 }
00331
00332
00333
00334
00335
00336 req->processingDoneTime = hs_vs + modeSwitchLag;
00337
00338
00339 req->processingDoneTime += lastReadout;
00340
00341
00342 req->processingDoneTime += req->frameTime;
00343
00344
00345
00346 int ispTime = 0;
00347 if (req->image.type == UYVY) {
00348 if (req->image.size.height > 1024 && req->image.size.width > 1024) {
00349 ispTime = 60000;
00350 }
00351 }
00352 req->processingDoneTime += ispTime;
00353
00354
00355 req->exposureStartTime = hs_vs + modeSwitchLag
00356 + req->frameTime - req->exposure;
00357
00358
00359
00360 if (req->f2Request->colSkip != prevReq.colSkip ||
00361 req->f2Request->colBin != prevReq.colBin ||
00362 req->f2Request->rowSkip != prevReq.rowSkip ||
00363 req->f2Request->rowBin != prevReq.rowBin) {
00364 if (req->f2Request->colSkip > prevReq.colSkip) {
00365
00366
00367
00368 } else {
00369
00370
00371 }
00372 } else {
00373
00374 }
00375
00376
00377 req->exposureEndTime = req->exposureStartTime + req->exposure + lastReadout;
00378
00379 dprintf(" Predicted time taken to read out previous frame: %d\n", lastReadout);
00380 dprintf(" Predicted time to expose and read out this frame: %d\n", req->frameTime);
00381 dprintf(" Predicted time to take in the ISP: %d\n", ispTime);
00382 dprintf(" Predicted processingDone: %d %d\n", req->processingDoneTime.s(), req->processingDoneTime.us());
00383 dprintf(" Predicted exposureEndTime: %d %d\n", req->exposureEndTime.s(), req->exposureEndTime.us());
00384
00385
00386 } else {
00387
00388
00389
00390 }
00391 }
00392
00393 void Daemon::setExposureParams(Frame *req, bool modeSwitch) {
00394 bool updatedParameters = false;
00395
00396
00397 if (req->f2Request->rowSkip != current.f2Request->rowSkip || modeSwitch){
00398 sensor->setControl(MT9P031_CID_ROW_SKIPPING, rowSkipDriver(req->f2Request->rowSkip) );
00399 current.f2Request->rowSkip = req->f2Request->rowSkip;
00400 updatedParameters = true;
00401 }
00402 if (req->f2Request->colSkip != current.f2Request->colSkip || modeSwitch){
00403 sensor->setControl(MT9P031_CID_COL_SKIPPING, colSkipDriver(req->f2Request->colSkip) );
00404 current.f2Request->colSkip = req->f2Request->colSkip;
00405 updatedParameters = true;
00406 }
00407 if (req->f2Request->rowBin != current.f2Request->rowBin || modeSwitch){
00408 sensor->setControl(MT9P031_CID_ROW_BINNING, rowBinDriver(req->f2Request->rowBin) );
00409 current.f2Request->rowBin = req->f2Request->rowBin;
00410 updatedParameters = true;
00411 }
00412 if (req->f2Request->colBin != current.f2Request->colBin || modeSwitch){
00413 sensor->setControl(MT9P031_CID_COL_BINNING, colBinDriver(req->f2Request->colBin) );
00414 current.f2Request->colBin = req->f2Request->colBin;
00415 updatedParameters = true;
00416 }
00417 if (req->f2Request->roiCentered ) {
00418 if (!current.f2Request->roiCentered || modeSwitch) {
00419 sensor->setControl(MT9P031_CID_ROI_X,
00420 MT9P031_ROI_AUTO_X);
00421 sensor->setControl(MT9P031_CID_ROI_Y,
00422 MT9P031_ROI_AUTO_Y);
00423 updatedParameters = true;
00424 }
00425 } else if (current.f2Request->roiCentered
00426 || req->f2Request->roiStartX != current.f2Request->roiStartX
00427 || req->f2Request->roiStartY != current.f2Request->roiStartY
00428 || modeSwitch) {
00429 sensor->setControl(MT9P031_CID_ROI_X,
00430 req->f2Request->roiStartX);
00431 sensor->setControl(MT9P031_CID_ROI_Y,
00432 req->f2Request->roiStartY);
00433 updatedParameters = true;
00434 }
00435 current.f2Request->roiCentered = req->f2Request->roiCentered;
00436 current.f2Request->roiStartX = req->f2Request->roiStartX;
00437 current.f2Request->roiStartY = req->f2Request->roiStartY;
00438
00439
00440 if (req->f2Request->frameTime != current.f2Request->frameTime
00441 || modeSwitch) {
00442 dprintf("new ft: %d\n", req->f2Request->frameTime);
00443 sensor->setFrameTime(req->f2Request->frameTime);
00444 current.f2Request->frameTime = req->f2Request->frameTime;
00445 updatedParameters = true;
00446 }
00447 if (req->f2Request->exposure != current.f2Request->exposure
00448 || modeSwitch) {
00449 dprintf("new exposure: %d\n", req->f2Request->exposure);
00450 sensor->setExposure(req->f2Request->exposure);
00451 current.f2Request->exposure = req->f2Request->exposure;
00452 updatedParameters = true;
00453 }
00454
00455
00456
00457 if (req->f2Request->gain != current.f2Request->gain || modeSwitch) {
00458 sensor->setGain(req->f2Request->gain);
00459 current.f2Request->gain = req->f2Request->gain;
00460 updatedParameters = true;
00461 }
00462
00463
00464
00465 if (updatedParameters)
00466 sensor->setControl(MT9P031_CID_WRITE_PARAMS, 0);
00467
00468
00469
00470 current.gain = req->gain = sensor->getGain();
00471
00472 current.exposure = req->exposure = sensor->getExposure();
00473 current.frameTime = req->frameTime = sensor->getFrameTime();
00474
00475 dprintf("actual exposure: %d\n", req->exposure);
00476 dprintf("actual ft: %d\n", req->frameTime);
00477
00478 current.rowSkip = req->rowSkip =
00479 rowSkipFCam(sensor->getControl(MT9P031_CID_ROW_SKIPPING));
00480 current.colSkip = req->colSkip =
00481 colSkipFCam(sensor->getControl(MT9P031_CID_COL_SKIPPING));
00482 current.rowBin = req->rowBin =
00483 rowBinFCam(sensor->getControl(MT9P031_CID_ROW_BINNING));
00484 current.colBin = req->colBin =
00485 colBinFCam(sensor->getControl(MT9P031_CID_COL_BINNING));
00486 current.roiStartX = req->roiStartX =
00487 sensor->getControl(MT9P031_CID_ROI_X);
00488 current.roiStartX = req->roiStartY =
00489 sensor->getControl(MT9P031_CID_ROI_Y);
00490
00491
00492
00493
00494
00495 }
00496
00497
00498 void Daemon::tickSetter(Time hs_vs) {
00499 static Frame *req = NULL;
00500 static Time prev_hs_vs;
00501 static bool wasModeswitch = false;
00502
00503
00504
00505 repeat_modeswitch:
00506 prev_hs_vs = hs_vs;
00507
00509
00510
00511 usleep(1000);
00512
00513
00514
00515 if (req) {
00516
00517 }
00518
00519
00520 setTimes(req, hs_vs, wasModeswitch);
00521 wasModeswitch = false;
00522
00523 if (req) {
00524 dprintf("TS: Pushing to inflight\n");
00525
00526
00527
00528
00529
00530 pthread_mutex_lock(&actionQueueMutex);
00531 for (std::set<FCam::Action*>::iterator i = req->f2Request->actions.begin();
00532 i != req->f2Request->actions.end();
00533 i++) {
00534 Action a;
00535 a.time = req->exposureStartTime + (*i)->time - (*i)->latency;
00536 a.action = (*i)->copy();
00537 actionQueue.push(a);
00538 }
00539 pthread_mutex_unlock(&actionQueueMutex);
00540 for (size_t i = 0; i < req->f2Request->actions.size(); i++) {
00541 sem_post(&actionQueueSemaphore);
00542 }
00543
00544 pthread_mutex_lock(&inFlightQueueMutex);
00545 inFlightQueue.push(req);
00546 pthread_mutex_unlock(&inFlightQueueMutex);
00547 req = NULL;
00548 } else {
00549
00550 }
00551
00553
00554
00555 if (generator && !requestQueue.size()) {
00556 dprintf("TS: Requesting generator\n");
00557 generator->generateRequest();
00558 }
00559
00560 pthread_mutex_lock(&requestQueueMutex);
00561 if (requestQueue.size()) {
00562 dprintf("TS: Grabbing next request \n");
00563
00564 req = requestQueue.front();
00565 } else {
00566
00567
00568
00569
00570 dprintf("TS: Creating a bubble request\n");
00571 req = new Frame;
00572 req->f2Request = new Shot;
00573
00574 req->f2Request->wanted = false;
00575
00576
00577
00578
00579 req->f2Request->image.size = current.f2Request->image.size;
00580 req->f2Request->image.type = current.f2Request->image.type;
00581
00582
00583
00584 req->f2Request->exposure = current.f2Request->exposure;
00585
00586
00587
00588 req->f2Request->histogram = current.f2Request->histogram;
00589 req->f2Request->sharpness = current.f2Request->sharpness;
00590 req->histogram.data = NULL;
00591 req->sharpness.data = NULL;
00592
00593
00594 requestQueue.push(req);
00595 }
00596 pthread_mutex_unlock(&requestQueueMutex);
00597
00598 prevReq = *current.f2Request;
00599
00600
00601
00602 if (req->f2Request->image.size != current.f2Request->image.size ||
00603 req->f2Request->image.type != current.f2Request->image.type ||
00604 req->f2Request->histogram != current.f2Request->histogram ||
00605 req->f2Request->sharpness != current.f2Request->sharpness) {
00606
00607 printf("TS: Mode Requested %d %d\n", req->f2Request->image.size.width, req->f2Request->image.size.height);
00608 printf("TS: Mode Current %d %d\n", current.f2Request->image.size.width, current.f2Request->image.size.height);
00609
00610
00611 dprintf("Setter: Mode switch required - flushing pipe\n");
00612 pipelineFlush = true;
00613
00614 pthread_mutex_lock(&cameraMutex);
00615 dprintf("Setter: Handler done flushing pipe, passing control back to setter\n");
00616
00617
00618
00619 if (current.image.size.width > 0) {
00620 printf("Setter: Stopping camera for mode switch\n");
00621 sensor->stopStreaming();
00622 sensor->close();
00623 sensor->open();
00624 } else {
00625 printf("Setter: Opening camera for the first time\n");
00626 sensor->open();
00627 }
00628
00629
00630 sensor->setControl(MT9P031_CID_DIRECT_MODE, 1);
00631
00632
00633 setReadoutParams(req, true);
00634 setExposureParams(req, true);
00635
00636
00637 V4L2Sensor::Mode m;
00638 m.width = req->f2Request->image.size.width;
00639 m.height = req->f2Request->image.size.height;
00640 m.type = req->f2Request->image.type;
00641
00642 sensor->startStreaming(m, &req->f2Request->histogram, &req->f2Request->sharpness);
00643
00644
00645
00646 current.frameTime = req->frameTime = sensor->getFrameTime();
00647 dprintf("Setter: First frame time %f ms\n", current.frameTime/1000.);
00648
00649 hs_vs = Time::now();
00650 dprintf("Setter: Setter done bringing up camera, passing control back to handler\n");
00651 pipelineFlush = false;
00652 pthread_mutex_unlock(&cameraMutex);
00653
00654 m = sensor->getMode();
00655 req->image.size.width = m.width;
00656 req->image.size.height = m.height;
00657 req->image.type = m.type;
00658
00659 current.f2Request->image.type = req->f2Request->image.type;
00660 current.f2Request->image.size = req->f2Request->image.size;
00661 current.f2Request->histogram = req->f2Request->histogram;
00662 current.f2Request->sharpness = req->f2Request->sharpness;
00663
00664 current.image.size.width = m.width;
00665 current.image.size.height = m.height;
00666 current.image.type = m.type;
00667
00668 dprintf("TS: Popping mode switch request\n");
00669
00670 pthread_mutex_lock(&requestQueueMutex);
00671 requestQueue.pop();
00672 pthread_mutex_unlock(&requestQueueMutex);
00673
00674 printf("TS: Mode switch done at %d %d, delta %f ms\n", hs_vs.s(), hs_vs.us(), (hs_vs-prev_hs_vs)/1000.0);
00675
00676 wasModeswitch = true;
00677 goto repeat_modeswitch;
00678 }
00679
00680 dprintf("Setter: no mode switch required\n");
00681 Time b = Time::now();
00682 setReadoutParams(req);
00683 setExposureParams(req);
00684 Time a = Time::now();
00685 dprintf(" Time to set %f ms\n", (a - b) / 1000.0);
00686
00687 dprintf("TS: Popping request\n");
00688
00689 pthread_mutex_lock(&requestQueueMutex);
00690 requestQueue.pop();
00691 pthread_mutex_unlock(&requestQueueMutex);
00692
00693 req->image.size = current.image.size;
00694 req->image.type = current.image.type;
00695
00696
00697
00698
00699
00700
00701
00702 }
00703
00704
00705 void Daemon::runHandler() {
00706 Frame *req = NULL;
00707 V4L2Sensor::V4L2Frame *f = NULL;
00708 Time prevDoneTime = Time::now();
00709
00710 pthread_mutex_lock(&cameraMutex);
00711
00712 while (!stop) {
00713
00714
00715
00716 if (!req && pipelineFlush && inFlightQueue.size() == 0) {
00717 printf("Handler: Handler done flushing pipe, passing control back to setter\n");
00718 while (pipelineFlush) {
00719 pthread_mutex_unlock(&cameraMutex);
00720
00721
00722
00723 usleep(10000);
00724 pthread_mutex_lock(&cameraMutex);
00725 }
00726 printf("Handler: Setter done bringing up camera, passing control back to handler\n");
00727
00728 }
00729
00730 if (pipelineFlush) {
00731 printf("Handler: Setter would like me to flush the pipeline, but I have requests in flight\n");
00732 }
00733
00734
00735 if (!f) {
00736 f = sensor->acquireFrame(true);
00737 }
00738
00739 if (!f) {
00740 printf("Handler got a NULL frame\n");
00741 usleep(10000);
00742 continue;
00743 }
00744
00745 dprintf("Handler: frame %d %d, delta %f\n",
00746 f->processingDoneTime.s(), f->processingDoneTime.us(),
00747 (f->processingDoneTime-prevDoneTime)/1000.);
00748 prevDoneTime = f->processingDoneTime;
00749
00750
00751 if (!req) {
00752 if (inFlightQueue.size()) {
00753
00754 pthread_mutex_lock(&inFlightQueueMutex);
00755 req = inFlightQueue.front();
00756 inFlightQueue.pop();
00757 pthread_mutex_unlock(&inFlightQueueMutex);
00758 } else {
00759
00760
00761
00762 int timeout = 5;
00763 while (timeout > 0 && (inFlightQueue.size()==0) ) {
00764 timeout--;
00765 usleep(1000);
00766 }
00767 if (timeout > 0) {
00768 pthread_mutex_lock(&inFlightQueueMutex);
00769 req = inFlightQueue.front();
00770 inFlightQueue.pop();
00771 pthread_mutex_unlock(&inFlightQueueMutex);
00772 } else {
00773 printf(" Giving up on waiting for request\n");
00774 sensor->releaseFrame(f);
00775 f = NULL;
00776 continue;
00777 }
00778 }
00779 }
00780 dprintf("Handler: Expected at %d %d, delta %f ms\n",
00781 req->processingDoneTime.s(), req->processingDoneTime.us(),
00782 (f->processingDoneTime - req->processingDoneTime)/1000.);
00783
00784
00785
00786 int dt = req->processingDoneTime - f->processingDoneTime;
00787
00788 if (dt < -25000 && !debugMode) {
00789 printf("Handler: Expected a frame at %d %d, but one didn't arrive until %d %d, dt %f ms\n",
00790 req->processingDoneTime.s(), req->processingDoneTime.us(),
00791 f->processingDoneTime.s(), f->processingDoneTime.us(),
00792 dt/1000.0);
00793 req->image.setData(Image::Discard);
00794 if (!req->f2Request->wanted) {
00795 delete req;
00796 } else {
00797
00798 sensor->getHistogram(req->exposureEndTime-2300, &req->histogram, &req->f2Request->histogram);
00799 sensor->getSharpnessMap(req->exposureEndTime-2300, &req->sharpness, &req->f2Request->sharpness);
00800
00801 pthread_mutex_lock(&frameQueueMutex);
00802 frameQueue.push(req);
00803 pthread_mutex_unlock(&frameQueueMutex);
00804 sem_post(&frameQueueSemaphore);
00805 enforceDropPolicy();
00806 }
00807 req = NULL;
00808 } else if (dt < 15000 || debugMode) {
00809
00810 if (!req->f2Request->wanted) {
00811
00812
00813 delete req;
00814 sensor->releaseFrame(f);
00815 } else {
00816
00817
00818 req->processingDoneTime = f->processingDoneTime;
00819
00820 size_t bytes = req->image.size.width*req->image.size.height*2;
00821 if (f->length < bytes) bytes = f->length;
00822
00823 if (req->shot().image.data == Image::AutoAllocate) {
00824 req->image = Image(req->image.size, req->image.type);
00825 memcpy(req->image.data, f->data, bytes);
00826 dprintf("Autoallocate: %d x %d, %d\n", req->image.size.width, req->image.size.height, req->image.data);
00827 } else if (req->shot().image.data == Image::Discard) {
00828 req->image.setData(Image::Discard);
00829 } else {
00830 if (req->image.size != req->shot().image.size) {
00831 printf("ERROR: Requested image size (%d x %d) "
00832 "on an already allocated image does not "
00833 "match actual image size (%d x %d). Dropping image data.\n",
00834 req->shot().image.size.width, req->shot().image.size.height,
00835 req->image.size.width, req->image.size.height);
00836 req->image.setData(Image::Discard);
00837 } else {
00838 req->image = req->shot().image;
00839
00840
00841 if(req->image.lock(10000)) {
00842 memcpy(req->image.data, f->data, bytes);
00843 req->image.unlock();
00844 } else {
00845 printf("WARNING: Daemon discarding image data (Target is locked)\n");
00846 req->image.setData(Image::Discard);
00847 }
00848 }
00849 }
00850
00851 sensor->releaseFrame(f);
00852 sensor->getHistogram(req->exposureEndTime-2300, &req->histogram, &req->f2Request->histogram);
00853 sensor->getSharpnessMap(req->exposureEndTime-2300, &req->sharpness, &req->f2Request->sharpness);
00854
00855 pthread_mutex_lock(&frameQueueMutex);
00856 frameQueue.push(req);
00857 pthread_mutex_unlock(&frameQueueMutex);
00858 sem_post(&frameQueueSemaphore);
00859 enforceDropPolicy();
00860
00861
00862
00863 }
00864
00865 req = NULL;
00866 f = NULL;
00867
00868 } else {
00869 printf("Handler: Received an early mystery frame (%d %d) vs (%d %d), dropping it.\n",
00870 f->processingDoneTime.s(), f->processingDoneTime.us(),
00871 req->processingDoneTime.s(), req->processingDoneTime.us());
00872 sensor->releaseFrame(f);
00873 f = NULL;
00874 }
00875
00876 }
00877 pthread_mutex_unlock(&cameraMutex);
00878
00879 }
00880
00881
00882 void Daemon::runAction() {
00883 printf("Action thread running...\n");
00884 while (1) {
00885 sem_wait(&actionQueueSemaphore);
00886 if (stop) break;
00887
00888 pthread_mutex_lock(&actionQueueMutex);
00889 Action a = actionQueue.top();
00890 actionQueue.pop();
00891 pthread_mutex_unlock(&actionQueueMutex);
00892
00893 Time t = Time::now();
00894 int delay = (a.time - t) - 500;
00895 if (delay > 0) usleep(delay);
00896 Time before = Time::now();
00897
00898 while (a.time > before) before = Time::now();
00899 a.action->doAction();
00900
00901 printf("Action thread: Initiated action %d us after scheduled time\n", before - a.time);
00902 delete a.action;
00903 }
00904 }
00905
00906 }}