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