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