00001 #include "Daemon.h"
00002 #include "linux/omap34xxcam-daemon.h"
00003
00004 #include "../Time.h"
00005 #include "../Frame.h"
00006 #include "../Action.h"
00007
00008 #include <errno.h>
00009 #include <sys/types.h>
00010 #include <sys/stat.h>
00011 #include <sys/fcntl.h>
00012 #include <sys/ioctl.h>
00013 #include <poll.h>
00014
00015 namespace FCam { namespace N900 {
00016
00017 void *daemon_setter_thread_(void *arg) {
00018 Daemon *d = (Daemon *)arg;
00019 d->runSetter();
00020 d->setterRunning = false;
00021 close(d->daemon_fd);
00022 pthread_exit(NULL);
00023 }
00024
00025 void *daemon_handler_thread_(void *arg) {
00026 Daemon *d = (Daemon *)arg;
00027 d->runHandler();
00028 d->handlerRunning = false;
00029 pthread_exit(NULL);
00030 }
00031
00032 void *daemon_action_thread_(void *arg) {
00033 Daemon *d = (Daemon *)arg;
00034 d->runAction();
00035 d->actionRunning = false;
00036 pthread_exit(NULL);
00037 }
00038
00039 Daemon::Daemon() :
00040 stop(false),
00041 generator(NULL),
00042 frameLimit(128),
00043 dropPolicy(Sensor::DropNewest),
00044 setterRunning(false),
00045 handlerRunning(false),
00046 actionRunning(false),
00047 waitingForFirstRequest(true) {
00048
00049
00050 current.request = new Shot;
00051
00052
00053 sensor = V4L2Sensor::instance("/dev/video0");
00054
00055
00056
00057
00058 if (getuid()) {
00059 printf("Camera Daemon can only run as root. Aborting.\n");
00060 return;
00061 }
00062
00063
00064 FILE *f = fopen("/proc/sys/kernel/sched_rt_runtime_us", "w");
00065 if (f) {
00066 fprintf(f, "-1");
00067 fclose(f);
00068 } else {
00069 printf("Could not enable real-time scheduling modes, daemon thread creating may fail\n");
00070 }
00071
00072
00073 if (!fork()) {
00074
00075 execl("/usr/sbin/dsmetool", "/usr/sbin/dsmetool", "-k", "/usr/bin/camera-ui", (char *)NULL);
00076
00077 perror("Failed to kill camera-ui");
00078 exit(0);
00079 }
00080
00081
00082 if ((errno =
00083 -(pthread_mutex_init(&requestQueueMutex, NULL) ||
00084 pthread_mutex_init(&frameQueueMutex, NULL) ||
00085 pthread_mutex_init(&actionQueueMutex, NULL) ||
00086 pthread_mutex_init(&inFlightQueueMutex, NULL) ||
00087 pthread_mutex_init(&cameraMutex, NULL)))) {
00088 perror("Error creating mutexes");
00089 }
00090
00091
00092 sem_init(&frameQueueSemaphore, 0, 0);
00093 sem_init(&actionQueueSemaphore, 0, 0);
00094
00095
00096 pipelineFlush = true;
00097
00098 }
00099
00100 void Daemon::launchThreads() {
00101
00102 pthread_attr_t attr;
00103 struct sched_param param;
00104
00105
00106
00107 param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
00108
00109 pthread_attr_init(&attr);
00110
00111 if ((errno =
00112 -(pthread_attr_setschedparam(&attr, ¶m) ||
00113 pthread_attr_setschedpolicy(&attr, SCHED_FIFO) ||
00114 pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) ||
00115 pthread_create(&setterThread, &attr, daemon_setter_thread_, this)))) {
00116 perror("Error creating daemon setter thread");
00117 return;
00118 } else {
00119 setterRunning = true;
00120 }
00121
00122
00123 param.sched_priority = sched_get_priority_min(SCHED_FIFO);
00124
00125 if ((errno =
00126 -(pthread_attr_setschedparam(&attr, ¶m) ||
00127 pthread_attr_setschedpolicy(&attr, SCHED_FIFO) ||
00128 pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) ||
00129 pthread_create(&handlerThread, &attr, daemon_handler_thread_, this)))) {
00130 perror("Error creating daemon handler thread");
00131 return;
00132 } else {
00133 handlerRunning = true;
00134 }
00135
00136
00137 param.sched_priority = sched_get_priority_max(SCHED_FIFO);
00138
00139 if ((errno =
00140 -(pthread_attr_setschedparam(&attr, ¶m) ||
00141 pthread_attr_setschedpolicy(&attr, SCHED_FIFO) ||
00142 pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) ||
00143 pthread_create(&actionThread, &attr, daemon_action_thread_, this)))) {
00144 perror("Error creating daemon action thread");
00145 return;
00146 } else {
00147 actionRunning = true;
00148 }
00149
00150 pthread_attr_destroy(&attr);
00151 }
00152
00153 Daemon::~Daemon() {
00154 stop = true;
00155
00156
00157 sem_post(&actionQueueSemaphore);
00158
00159 if (setterRunning)
00160 pthread_join(setterThread, NULL);
00161
00162 if (handlerRunning)
00163 pthread_join(handlerThread, NULL);
00164
00165 if (actionRunning)
00166 pthread_join(actionThread, NULL);
00167
00168 pthread_mutex_destroy(&requestQueueMutex);
00169 pthread_mutex_destroy(&frameQueueMutex);
00170 pthread_mutex_destroy(&inFlightQueueMutex);
00171 pthread_mutex_destroy(&actionQueueMutex);
00172
00173 sensor->stopStreaming();
00174
00175 sensor->close();
00176 }
00177
00178
00179 void Daemon::setRequestGenerator(Daemon::RequestGenerator *gen) {
00180 generator = gen;
00181 if (waitingForFirstRequest && generator) {
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 tickSetter(Time::now());
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
00219 void Daemon::setDropPolicy(Sensor::DropPolicy p, int f) {
00220 dropPolicy = p;
00221 frameLimit = f;
00222 enforceDropPolicy();
00223 }
00224
00225 void Daemon::enforceDropPolicy() {
00226 if (frameQueue.size() > frameLimit) {
00227 pthread_mutex_lock(&frameQueueMutex);
00228 int drops = frameQueue.size() - frameLimit;
00229 if (drops > 0) {
00230 printf("WARNING: frame limit hit (%d), silently dropping %d frames.\n"
00231 "You're not draining the frame queue quickly enough. Use longer \n"
00232 "frame times or drain the frame queue until empty every time you \n"
00233 "call getFrame()\n", frameLimit, drops);
00234 if (dropPolicy == Sensor::DropOldest) {
00235 for (int i = 0; i < drops; i++) {
00236 sem_wait(&frameQueueSemaphore);
00237 delete frameQueue.front();
00238 frameQueue.pop();
00239 }
00240 } else if (dropPolicy == Sensor::DropNewest) {
00241
00242 for (size_t i = 0; i < frameQueue.size() - drops; i++) {
00243 frameQueue.push(frameQueue.front());
00244 frameQueue.pop();
00245 }
00246 for (int i = 0; i < drops; i++) {
00247 sem_wait(&frameQueueSemaphore);
00248 delete frameQueue.front();
00249 frameQueue.pop();
00250 }
00251 } else {
00252 printf("Unknown drop policy! Not dropping frames.\n");
00253 }
00254 }
00255 pthread_mutex_unlock(&frameQueueMutex);
00256 }
00257 }
00258
00259 void Daemon::runSetter() {
00260
00261 daemon_fd = open("/dev/video0", O_RDWR, 0);
00262
00263 if (daemon_fd < 0) {
00264 perror("opening /dev/video0 as daemon");
00265 return;
00266 }
00267
00268
00269 if (ioctl(daemon_fd, VIDIOC_DAEMON_INSTALL, NULL)) {
00270 perror("VIDIOC_DAEMON_INSTALL");
00271 return;
00272 }
00273
00274 unsigned int event_mask = 8;
00275 if (ioctl(daemon_fd, VIDIOC_DAEMON_SET_EVENTS, &event_mask)) {
00276 perror("VIDIOC_DAEMON_SET_EVENTS");
00277 return;
00278 }
00279
00280
00281 struct pollfd p = {daemon_fd, POLLIN, 0};
00282
00283 struct omap34xxcam_daemon_daemon_req req;
00284
00285 req.req.blob = malloc(1<<10);
00286 req.req.max_size = 1<<10;
00287
00288 while (!stop) {
00289
00290 poll(&p, 1, 1000);
00291 if (p.revents & POLLIN) {
00292
00293
00294 req.u.sync = 0;
00295 req.req.size = 0;
00296 req.req.type = 0;
00297
00298 if (ioctl(daemon_fd, VIDIOC_DAEMON_DAEMON_REQ_GET, &req)) {
00299 perror("VIDIOC_DAEMON_DAEMON_REQ_GET");
00300
00301
00302
00303
00304 usleep(10000);
00305 continue;
00306 }
00307
00308 if (req.req.type == 1000) {
00309
00310
00311 if (ioctl(daemon_fd, VIDIOC_DAEMON_DAEMON_REQ_COMPLETE, &req)) {
00312 perror("VIDIOC_DAEMON_DAEMON_REQ_COMPLETE");
00313
00314 }
00315
00316
00317 } else if (req.req.type == 10) {
00318
00319 struct omap34xxcam_daemon_event *event =
00320 (struct omap34xxcam_daemon_event *)req.req.blob;
00321
00322
00323 if (event->mask == 8) {
00324 tickSetter(Time(event->hs_vs_stamp));
00325 }
00326 }
00327
00328 } else {
00329
00330
00331 }
00332 }
00333
00334 }
00335
00336 void Daemon::tickSetter(Time hs_vs) {
00337 static Frame *req = NULL;
00338
00339
00340 static int lastReadout = 33000;
00341
00342 static bool ignoreNextHSVS = false;
00343
00344 if (ignoreNextHSVS) {
00345 ignoreNextHSVS = false;
00346 return;
00347 }
00348
00349 if (req) {
00350
00351
00352
00353 if (req->request->gain != current.request->gain) {
00354 sensor->setGain(req->request->gain);
00355 current.request->gain = req->request->gain;
00356 }
00357 current.gain = req->gain = sensor->getGain();
00358
00359
00360
00361
00362
00363 req->processingDoneTime = hs_vs;
00364
00365
00366 req->processingDoneTime += lastReadout;
00367
00368
00369 req->processingDoneTime += req->frameTime;
00370
00371
00372
00373 int ispTime = 0;
00374 if (req->image.type == UYVY) {
00375 if (req->image.size.height > 1024 && req->image.size.width > 1024) {
00376 ispTime = 65000;
00377 } else {
00378 ispTime = 10000;
00379 }
00380 }
00381 req->processingDoneTime += ispTime;
00382
00383
00384 req->exposureStartTime = hs_vs + req->frameTime - req->exposure;
00385
00386
00387
00388 lastReadout = (current.image.size.height > 1008) ? 76000 : 33000;
00389
00390 req->exposureEndTime = req->exposureStartTime + req->exposure + lastReadout;
00391
00392
00393
00394
00395
00396
00397 pthread_mutex_lock(&actionQueueMutex);
00398 for (std::set<FCam::Action*>::iterator i = req->request->actions.begin();
00399 i != req->request->actions.end();
00400 i++) {
00401 Action a;
00402 a.time = req->exposureStartTime + (*i)->time - (*i)->latency;
00403 a.action = (*i)->copy();
00404 actionQueue.push(a);
00405 }
00406 pthread_mutex_unlock(&actionQueueMutex);
00407 for (size_t i = 0; i < req->request->actions.size(); i++) {
00408 sem_post(&actionQueueSemaphore);
00409 }
00410
00411 pthread_mutex_lock(&inFlightQueueMutex);
00412 inFlightQueue.push(req);
00413 pthread_mutex_unlock(&inFlightQueueMutex);
00414 req = NULL;
00415 } else {
00416
00417 lastReadout = (current.image.size.height > 1008) ? 76000 : 33000;
00418 }
00419
00420
00421
00422
00423 if (generator && !requestQueue.size()) {
00424 generator->generateRequest();
00425 }
00426
00427 pthread_mutex_lock(&requestQueueMutex);
00428 if (requestQueue.size()) {
00429
00430 req = requestQueue.front();
00431 } else {
00432
00433
00434
00435
00436
00437
00438 req = new Frame;
00439 req->request = new Shot;
00440 req->request->wanted = false;
00441
00442
00443
00444
00445
00446 req->request->image.size = current.request->image.size;
00447 req->request->image.type = current.request->image.type;
00448
00449
00450
00451 req->request->histogram = current.request->histogram;
00452 req->request->sharpness = current.request->sharpness;
00453 req->histogram.data = NULL;
00454 req->sharpness.data = NULL;
00455
00456
00457 requestQueue.push(req);
00458 }
00459 pthread_mutex_unlock(&requestQueueMutex);
00460
00461
00462 if (req->request->image.size != current.request->image.size ||
00463 req->request->image.type != current.request->image.type ||
00464 req->request->histogram != current.request->histogram ||
00465 req->request->sharpness != current.request->sharpness) {
00466
00467 printf("Setter: Request %d %d\n", req->request->image.size.width, req->request->image.size.height);
00468 printf("Setter: Current %d %d\n", current.request->image.size.width, current.request->image.size.height);
00469
00470
00471 printf("Setter: Mode switch required - flushing pipe\n");
00472 pipelineFlush = true;
00473
00474 pthread_mutex_lock(&cameraMutex);
00475 printf("Setter: Handler done flushing pipe, passing control back to setter\n");
00476
00477
00478
00479 if (current.image.size.width > 0) {
00480 printf("Setter: Shutting down camera\n");
00481 sensor->stopStreaming();
00482 sensor->close();
00483 }
00484 printf("Setter: Starting up camera in new mode\n");
00485 sensor->open();
00486
00487
00488 V4L2Sensor::Mode m;
00489 m.width = req->request->image.size.width;
00490 m.height = req->request->image.size.height;
00491 m.type = req->request->image.type;
00492 sensor->startStreaming(m, &req->request->histogram, &req->request->sharpness);
00493 sensor->setFrameTime(0);
00494
00495 printf("Setter: Setter done bringing up camera, passing control back "
00496 "to handler. Expect two mystery frames.\n");
00497 pipelineFlush = false;
00498 pthread_mutex_unlock(&cameraMutex);
00499
00500 m = sensor->getMode();
00501 req->image.size.width = m.width;
00502 req->image.size.height = m.height;
00503 req->image.type = m.type;
00504
00505 current.request->image.type = req->request->image.type;
00506 current.request->image.size = req->request->image.size;
00507 current.request->histogram = req->request->histogram;
00508 current.request->sharpness = req->request->sharpness;
00509
00510
00511
00512 current.request->frameTime = -1;
00513 current.request->exposure = -1;
00514 current.request->gain = -1.0;
00515
00516 current.image.size.width = m.width;
00517 current.image.size.height = m.height;
00518 current.image.type = m.type;
00519
00520 req = NULL;
00521
00522
00523 ignoreNextHSVS = true;
00524
00525 return;
00526 } else {
00527
00528 }
00529
00530
00531 pthread_mutex_lock(&requestQueueMutex);
00532 requestQueue.pop();
00533 pthread_mutex_unlock(&requestQueueMutex);
00534
00535 int exposure = req->request->exposure;
00536 int frameTime = req->request->frameTime;
00537
00538 if (frameTime < exposure + 400) {
00539 frameTime = exposure + 400;
00540 }
00541
00542
00543 sensor->setFrameTime(frameTime);
00544 sensor->setExposure(exposure);
00545
00546
00547
00548 current.request->frameTime = frameTime;
00549 current.request->exposure = exposure;
00550 current.exposure = req->exposure = sensor->getExposure();
00551 current.frameTime = req->frameTime = sensor->getFrameTime();
00552 req->image.size = current.image.size;
00553 req->image.type = current.image.type;
00554
00555
00556
00557
00558
00559
00560 }
00561
00562
00563 void Daemon::runHandler() {
00564 Frame *req = NULL;
00565 V4L2Sensor::V4L2Frame *f = NULL;
00566
00567 pthread_mutex_lock(&cameraMutex);
00568
00569 while (!stop) {
00570
00571
00572
00573 if (!req && pipelineFlush && inFlightQueue.size() == 0) {
00574 printf("Handler: Handler done flushing pipe, passing control back to setter\n");
00575 while (pipelineFlush) {
00576 pthread_mutex_unlock(&cameraMutex);
00577
00578
00579
00580 usleep(10000);
00581 pthread_mutex_lock(&cameraMutex);
00582 }
00583 printf("Handler: Setter done bringing up camera, passing control back to handler\n");
00584
00585 }
00586
00587 if (pipelineFlush) {
00588 printf("Handler: Setter would like me to flush the pipeline, but I have requests in flight\n");
00589 }
00590
00591
00592 if (!f)
00593 f = sensor->acquireFrame(true);
00594
00595 if (!f) {
00596 printf("Handler got a NULL frame\n");
00597 usleep(300000);
00598 continue;
00599 }
00600
00601
00602 if (!req) {
00603 if (inFlightQueue.size()) {
00604
00605 pthread_mutex_lock(&inFlightQueueMutex);
00606 req = inFlightQueue.front();
00607 inFlightQueue.pop();
00608 pthread_mutex_unlock(&inFlightQueueMutex);
00609 } else {
00610
00611
00612 printf("Handler: Got a frame without an outstanding request, "
00613 "dropping it.\n");
00614 sensor->releaseFrame(f);
00615 f = NULL;
00616 continue;
00617 }
00618 }
00619
00620
00621
00622 int dt = req->processingDoneTime - f->processingDoneTime;
00623
00624
00625
00626 if (dt < -25000) {
00627 printf("Handler: Expected a frame at %d %d, but one didn't arrive until %d %d\n",
00628 req->processingDoneTime.s(), req->processingDoneTime.us(),
00629 f->processingDoneTime.s(), f->processingDoneTime.us());
00630 req->image.setData(Image::Discard);
00631 if (!req->request->wanted) {
00632 delete req;
00633 } else {
00634
00635 sensor->getHistogram(req->exposureEndTime, &req->histogram, &req->request->histogram);
00636 sensor->getSharpnessMap(req->exposureEndTime, &req->sharpness, &req->request->sharpness);
00637 pthread_mutex_lock(&frameQueueMutex);
00638 frameQueue.push(req);
00639 pthread_mutex_unlock(&frameQueueMutex);
00640 sem_post(&frameQueueSemaphore);
00641 enforceDropPolicy();
00642 }
00643 req = NULL;
00644 } else if (dt < 10000) {
00645
00646 if (!req->request->wanted) {
00647
00648
00649 delete req;
00650 sensor->releaseFrame(f);
00651 } else {
00652
00653
00654 req->processingDoneTime = f->processingDoneTime;
00655
00656 size_t bytes = req->image.size.width*req->image.size.height*2;
00657 if (f->length < bytes) bytes = f->length;
00658
00659 if (req->shot().image.data == Image::AutoAllocate) {
00660 req->image = Image(req->image.size, req->image.type);
00661 memcpy(req->image.data, f->data, bytes);
00662 } else if (req->shot().image.data == Image::Discard) {
00663 req->image.setData(Image::Discard);
00664 } else {
00665 if (req->image.size != req->shot().image.size) {
00666 printf("ERROR: Requested image size (%d x %d) "
00667 "on an already allocated image does not "
00668 "match actual image size (%d x %d). Dropping image data.\n",
00669 req->shot().image.size.width, req->shot().image.size.height,
00670 req->image.size.width, req->image.size.height);
00671 req->image.setData(Image::Discard);
00672 } else {
00673 req->image = req->shot().image;
00674
00675
00676 Time lockStart = Time::now();
00677 if (req->image.lock(10000)) {
00678 memcpy(req->image.data, f->data, bytes);
00679 req->image.unlock();
00680 } else {
00681 printf("WARNING: Daemon discarding image data (target is still locked, "
00682 "waited for %d us)\n", Time::now() - lockStart);
00683 req->image.setData(Image::Discard);
00684 }
00685 }
00686 }
00687
00688 sensor->releaseFrame(f);
00689 sensor->getHistogram(req->exposureEndTime, &req->histogram, &req->request->histogram);
00690 sensor->getSharpnessMap(req->exposureEndTime, &req->sharpness, &req->request->sharpness);
00691
00692 pthread_mutex_lock(&frameQueueMutex);
00693 frameQueue.push(req);
00694 pthread_mutex_unlock(&frameQueueMutex);
00695 sem_post(&frameQueueSemaphore);
00696 enforceDropPolicy();
00697
00698
00699
00700
00701
00702
00703
00704 }
00705
00706 req = NULL;
00707 f = NULL;
00708
00709 } else {
00710 printf("Handler: Received an early mystery frame (%d %d) vs (%d %d), dropping it.\n",
00711 f->processingDoneTime.s(), f->processingDoneTime.us(),
00712 req->processingDoneTime.s(), req->processingDoneTime.us());
00713 sensor->releaseFrame(f);
00714 f = NULL;
00715 }
00716
00717 }
00718 pthread_mutex_unlock(&cameraMutex);
00719
00720 }
00721
00722
00723 void Daemon::runAction() {
00724 printf("Action thread running...\n");
00725 while (1) {
00726 sem_wait(&actionQueueSemaphore);
00727 if (stop) break;
00728
00729 pthread_mutex_lock(&actionQueueMutex);
00730 Action a = actionQueue.top();
00731 actionQueue.pop();
00732 pthread_mutex_unlock(&actionQueueMutex);
00733
00734 Time t = Time::now();
00735 int delay = (a.time - t) - 500;
00736 if (delay > 0) usleep(delay);
00737 Time before = Time::now();
00738
00739 while (a.time > before) before = Time::now();
00740 a.action->doAction();
00741
00742 printf("Action thread: Initiated action %d us after scheduled time\n", before - a.time);
00743 delete a.action;
00744 }
00745 }
00746
00747 }}
00748