00001 #include <FCam/Event.h>
00002 #include <FCam/processing/DNG.h>
00003
00004 #include "Daemon.h"
00005 #include "../Debug.h"
00006
00007 namespace FCam {
00008 namespace Dummy {
00009
00010 Daemon::Daemon(Sensor *sensor): sensor(sensor), stop(false), running(false) {
00011 }
00012
00013 Daemon::~Daemon() {
00014 stop = true;
00015
00016 if (running) {
00017 pthread_join(simThread, NULL);
00018 }
00019
00020 }
00021
00022 void Daemon::launchThreads() {
00023 int err = pthread_create(&simThread, NULL, daemon_launch_thread_, this);
00024 if (err) {
00025 error(Event::InternalError, sensor, "Dummy::Sensor::Daemon: Can't launch simulation thread\n");
00026 return;
00027 }
00028 }
00029
00030 void Daemon::run() {
00031 while (!stop) {
00032 if (!requestQueue.size()) {
00033 sensor->generateRequest();
00034 }
00035
00036 if (!requestQueue.size()) {
00037 timespec sleepDuration;
00038 sleepDuration.tv_sec = 0;
00039 sleepDuration.tv_nsec = 100e6;
00040 dprintf(5, "Dummy::Sensor::Daemon: Empty queue, sleeping for a bit\n");
00041 nanosleep(&sleepDuration, NULL);
00042 continue;
00043 }
00044 dprintf(4, "Dummy::Sensor::Daemon: Processing new request\n");
00045 _Frame *f = requestQueue.pull();
00046
00047 f->exposureStartTime = Time::now();
00048 f->exposureEndTime = f->exposureStartTime + f->shot().exposure;
00049 f->exposure = f->shot().exposure;
00050 f->gain = f->shot().gain;
00051 f->whiteBalance = f->shot().whiteBalance;
00052 f->testPattern = f->shot().testPattern;
00053 f->srcFile = f->shot().srcFile;
00054
00055 timespec frameDuration;
00056 int duration = (f->shot().exposure > f->shot().frameTime ?
00057 f->shot().exposure : f->shot().frameTime);
00058 frameDuration.tv_sec = duration / 1000000;
00059 frameDuration.tv_nsec = 1000 * (duration % 1000000);
00060
00061 dprintf(4, "Dummy::Sensor::Daemon: Sleeping for frame duration %d us (%d s %d nsec) at %s\n", duration, frameDuration.tv_sec, frameDuration.tv_nsec,f->exposureStartTime.toString().c_str());
00062 nanosleep(&frameDuration, NULL);
00063 dprintf(4, "Dummy::Sensor::Daemon: Done sleeping at %s\n", Time::now().toString().c_str());
00064 f->frameTime = Time::now() - f->exposureStartTime;
00065
00066 f->image = f->shot().image;
00067 if (f->image.autoAllocate()) {
00068 f->image = Image(f->image.size(), f->image.type());
00069 }
00070
00071 switch (f->testPattern) {
00072 case BARS:
00073 case CHECKERBOARD:
00074 dprintf(4, "Dummy::Sensor::Daemon: Drawing test pattern\n");
00075 if (!f->image.discard()) {
00076 for (unsigned int y=0; y < f->image.height(); y++) {
00077 for (unsigned int x=0; x < f->image.width(); x++) {
00078 int fX = 10000*x / (f->image.width()-1);
00079 int fY = 10000*y / (f->image.height()-1);
00080
00081 unsigned short lum;
00082 unsigned short rawR=0, rawG=0, rawB=0;
00083
00084 switch (f->testPattern) {
00085 case BARS:
00086 if (fY < 5000) {
00087
00088 if (fX < 2500) {
00089 lum = (fX / 100) * 900 / 25 + 100;
00090 rawR = ((fX / 100) % 2) * lum;
00091 rawG = ((fX / 100) % 2) * lum;
00092 rawB = ((fX / 100) % 2) * lum;
00093 } else if (fX < 5000) {
00094 lum = ((fX - 2500)/ 100) * 900/ 25 + 100;
00095 rawR = ((fX / 100) % 2) * lum;
00096 rawG = ((fX / 100) % 2) * lum / 100;
00097 rawB = ((fX / 100) % 2) * lum / 100;
00098 } else if (fX < 7500) {
00099 lum = ((fX - 5000)/ 100) * 900/ 25 + 100;
00100 rawR = ((fX / 100) % 2) * lum / 100;
00101 rawG = ((fX / 100) % 2) * lum;
00102 rawB = ((fX / 100) % 2) * lum / 100;
00103 } else {
00104 lum = ((fX - 7500)/ 100) * 900/ 25 + 100;
00105 rawR = ((fX / 100) % 2) * lum / 100;
00106 rawG = ((fX / 100) % 2) * lum / 100;
00107 rawB = ((fX / 100) % 2) * lum;
00108 }
00109 } else {
00110
00111 if (fX < 2500) {
00112 rawR = ((fY / 100) % 2) * 1000;
00113 rawG = ((fY / 100) % 2) * 1000;
00114 rawB = ((fY / 100) % 2) * 1000;
00115 } else if (fX < 5000) {
00116 rawR = ((fY / 100) % 2) * 1000;
00117 rawG = 10;
00118 rawB = 10;
00119 } else if (fX < 7500) {
00120 rawR = 10;
00121 rawG = ((fY / 100) % 2) * 1000;
00122 rawB = 10;
00123 } else {
00124 rawR = 10;
00125 rawG = 10;
00126 rawB = ((fY / 100) % 2) * 1000;
00127 }
00128 }
00129 break;
00130 case CHECKERBOARD:
00131 if (fX < 5000) {
00132 if (fY < 5000) {
00133 lum = fX * 900 / 5000 + 100;
00134 rawR =
00135 (((fX / 250) % 2) ^
00136 ((fY / 250) % 2)) *
00137 lum;
00138 rawG = rawR;
00139 rawB = rawR;
00140 } else {
00141 lum = fX * 900 / 5000 + 100;
00142 rawR =
00143 (((fX / 250) % 2) ^
00144 ((fY / 250) % 2)) *
00145 lum;
00146 rawG = rawR/100;
00147 rawB = rawR/100;
00148 }
00149 } else {
00150 if (fY < 5000) {
00151 lum = (fX-5000) * 900 / 5000 + 100;
00152 rawG =
00153 (((fX / 250) % 2) ^
00154 ((fY / 250) % 2)) *
00155 lum;
00156 rawR = rawG/100;
00157 rawB = rawG/100;
00158 } else {
00159 lum = (fX-5000) * 900 / 5000 + 100;
00160 rawB =
00161 (((fX / 250) % 2) ^
00162 ((fY / 250) % 2)) *
00163 lum;
00164 rawR = rawB/100;
00165 rawG = rawB/100;
00166 }
00167 }
00168 break;
00169 default:
00170 break;
00171 }
00172
00173 rawR *= f->gain*f->exposure/10000;
00174 rawG *= f->gain*f->exposure/10000;
00175 rawB *= f->gain*f->exposure/10000;
00176
00177 switch (f->image.type()) {
00178 case RGB24: {
00179 unsigned char *px = f->image(x,y);
00180 px[0] = rawR > 1000 ? 250 : rawR / 4;
00181 px[1] = rawG > 1000 ? 250 : rawG / 4;
00182 px[2] = rawB > 1000 ? 250 : rawB / 4;
00183 break;
00184 }
00185 case RGB16: {
00186 unsigned short *px = (unsigned short *)f->image(x,y);
00187 unsigned char r =rawR > 1000 ? 250 : rawR / 4;
00188 unsigned char g = rawG > 1000 ? 250 : rawG / 4;
00189 unsigned char b = rawB > 1000 ? 250 : rawB / 4;
00190 *px = ((r / 8) |
00191 ((g / 4) << 5) |
00192 ((b / 8) << 11));
00193 break;
00194 }
00195 case UYVY: {
00196 unsigned char *px = (unsigned char *)f->image(x,y);
00197 unsigned char r =rawR > 1000 ? 250 : rawR / 4;
00198 unsigned char g = rawG > 1000 ? 250 : rawG / 4;
00199 unsigned char b = rawB > 1000 ? 250 : rawB / 4;
00200 unsigned char y = 0.299 * r + 0.587 * g + 0.114 * b;
00201 unsigned char u = 128 - 0.168736 *r - 0.331264 * g + 0.5 * b;
00202 unsigned char v = 128 + 0.5*r - 0.418688*g - 0.081312*b;
00203 px[0] = (x % 2) ? u : v;
00204 px[1] = y;
00205 break;
00206 }
00207 case YUV24: {
00208 unsigned char *px = (unsigned char *)f->image(x,y);
00209 unsigned char r =rawR > 1000 ? 250 : rawR / 4;
00210 unsigned char g = rawG > 1000 ? 250 : rawG / 4;
00211 unsigned char b = rawB > 1000 ? 250 : rawB / 4;
00212 px[0] = 0.299 * r + 0.587 * g + 0.114 * b;
00213 px[1] = 128 - 0.168736 *r - 0.331264 * g + 0.5 * b;
00214 px[2] = 128 + 0.5*r - 0.418688*g - 0.081312*b;
00215 break;
00216 }
00217 case RAW: {
00218 unsigned short rawVal;
00219 if ((x % 2 == 0 && y % 2 == 0) ||
00220 (x % 2 == 1 && y % 2 == 1)) {
00221 rawVal = rawG;
00222 } else if (x % 2 == 1 && y % 2 == 0) {
00223 rawVal = rawR;
00224 } else {
00225 rawVal = rawB;
00226 }
00227
00228 *(unsigned short *)f->image(x,y) = rawVal;
00229 break;
00230 }
00231 default:
00232 break;
00233 }
00234 }
00235 }
00236 }
00237 f->_bayerPattern = sensor->platform().bayerPattern();
00238 f->_minRawValue = sensor->platform().minRawValue();
00239 f->_maxRawValue = sensor->platform().maxRawValue();
00240 f->_manufacturer = sensor->platform().manufacturer();
00241 f->_model = sensor->platform().model();
00242 sensor->platform().rawToRGBColorMatrix(3200, f->rawToRGB3200K);
00243 sensor->platform().rawToRGBColorMatrix(7000, f->rawToRGB7000K);
00244 f->processingDoneTime = Time::now();
00245 break;
00246 case FILE:
00247 if (f->image.type() != RAW) {
00248 error(Event::InternalError, sensor, "Dummy::Sensor: Non-RAW image requested from a source DNG file. Not supported.");
00249 f->image = Image();
00250 } else {
00251 dprintf(4, "Dummy::Sensor::Daemon: Loading %s\n", f->srcFile.c_str());
00252 FCam::Frame dng = loadDNG(f->srcFile);
00253 if (!dng.valid()) {
00254 error(Event::InternalError, sensor, "Dummy::Sensor: Unable to load file %s as a source Frame.", f->srcFile.c_str());
00255 } else {
00256 if (!f->image.discard()) {
00257 f->image = dng.image();
00258 } else {
00259 f->image = Image(dng.image().size(), dng.image().type(), Image::Discard);
00260 }
00261 f->exposureStartTime = dng.exposureStartTime();
00262 f->exposureEndTime = dng.exposureEndTime();
00263 f->processingDoneTime = dng.processingDoneTime();
00264 f->exposure = dng.exposure();
00265 f->frameTime = dng.frameTime();
00266 f->gain = dng.gain();
00267 f->whiteBalance = dng.whiteBalance();
00268 f->histogram = dng.histogram();
00269 f->sharpness = dng.sharpness();
00270 f->tags = dng.tags();
00271 f->_bayerPattern = dng.platform().bayerPattern();
00272 f->_minRawValue = dng.platform().minRawValue();
00273 f->_maxRawValue = dng.platform().maxRawValue();
00274 f->_manufacturer = dng.platform().manufacturer();
00275 f->_model = dng.platform().model();
00276 dng.platform().rawToRGBColorMatrix(3200, f->rawToRGB3200K);
00277 dng.platform().rawToRGBColorMatrix(7000, f->rawToRGB7000K);
00278 }
00279 }
00280 }
00281 frameQueue.push(f);
00282 }
00283 }
00284
00285 void *daemon_launch_thread_(void *arg) {
00286 Daemon *d = (Daemon *)arg;
00287 dprintf(DBG_MINOR, "Dummy::Sensor: Launching dummy simulator thread\n");
00288 d->running = true;
00289 d->run();
00290 d->running = false;
00291 pthread_exit(NULL);
00292 return NULL;
00293 }
00294
00295 }
00296 }