00001 #include <sys/ioctl.h>
00002 #include <linux/videodev2.h>
00003
00004 #include "FCam/N900/Flash.h"
00005 #include "FCam/Frame.h"
00006
00007 #include "../Debug.h"
00008 #include "V4L2Sensor.h"
00009
00010 namespace FCam { namespace N900 {
00011
00012 Flash::Flash() : flashHistory(512) {
00013 }
00014
00015 Flash::~Flash() {}
00016
00017 void Flash::setBrightness(float b) {
00018 if (b < minBrightness()) b = minBrightness();
00019 if (b > maxBrightness()) b = maxBrightness();
00020 struct v4l2_control ctrl;
00021 ctrl.id = V4L2_CID_FLASH_INTENSITY;
00022 ctrl.value = b;
00023 int fd = V4L2Sensor::instance("/dev/video0")->getFD();
00024 if (fd < 0) {
00025 V4L2Sensor::instance("/dev/video0")->open();
00026 fd = V4L2Sensor::instance("/dev/video0")->getFD();
00027 }
00028 if (ioctl(fd, VIDIOC_S_CTRL, &ctrl) < 0) {
00029 error(Event::DriverError, this, "VIDIOC_S_CTRL: %d = %d, %d", ctrl.id, ctrl.value, errno);
00030 return;
00031 }
00032 }
00033
00034
00035 void Flash::setDuration(int d) {
00036 if (d < minDuration()) d = minDuration();
00037 if (d > maxDuration()) d = maxDuration();
00038 struct v4l2_control ctrl;
00039 ctrl.id = V4L2_CID_FLASH_TIMEOUT;
00040 ctrl.value = d;
00041 int fd = V4L2Sensor::instance("/dev/video0")->getFD();
00042 if (fd < 0) {
00043 V4L2Sensor::instance("/dev/video0")->open();
00044 fd = V4L2Sensor::instance("/dev/video0")->getFD();
00045 }
00046 if (ioctl(fd, VIDIOC_S_CTRL, &ctrl) < 0) {
00047 error(Event::DriverError, this, "VIDIOC_S_CTRL: %d = %d, %d", ctrl.id, ctrl.value, errno);
00048 return;
00049 }
00050 }
00051
00052 void Flash::fire(float brightness, int duration) {
00053 Time fireTime = Time::now() + fireLatency();
00054 setBrightness(brightness);
00055 setDuration(duration);
00056
00057 struct v4l2_control ctrl;
00058 ctrl.id = V4L2_CID_FLASH_STROBE;
00059 ctrl.value = 0;
00060 int fd = V4L2Sensor::instance("/dev/video0")->getFD();
00061 if (fd < 0) {
00062 V4L2Sensor::instance("/dev/video0")->open();
00063 fd = V4L2Sensor::instance("/dev/video0")->getFD();
00064 }
00065 if (ioctl(fd, VIDIOC_S_CTRL, &ctrl) < 0) {
00066 error(Event::DriverError, this, "VIDIOC_S_CTRL: %d = %d, %d", ctrl.id, ctrl.value, errno);
00067 } else {
00068 FlashState f;
00069 f.time = fireTime;
00070 f.brightness = brightness;
00071 flashHistory.push(f);
00072 f.time = fireTime + duration;
00073 f.brightness = 0;
00074 flashHistory.push(f);
00075 }
00076 }
00077
00078 void Flash::tagFrame(FCam::Frame f) {
00079 Time t1 = f.exposureStartTime();
00080 Time t2 = f.exposureEndTime();
00081
00082
00083 float b1 = 0;
00084 float b2 = 0;
00085
00086 for (size_t i = 0; i < flashHistory.size(); i++) {
00087 if (t1 > flashHistory[i].time) {
00088 b1 = flashHistory[i].brightness;
00089 break;
00090 }
00091 }
00092
00093 for (size_t i = 0; i < flashHistory.size(); i++) {
00094 if (t2 > flashHistory[i].time) {
00095 b2 = flashHistory[i].brightness;
00096 break;
00097 }
00098 }
00099
00100
00101
00102 int offTime = -1, onTime = -1;
00103 float brightness;
00104 for (size_t i = 0; i < flashHistory.size(); i++) {
00105 if (flashHistory[i].time < t1) break;
00106 if (flashHistory[i].time > t2) continue;
00107 if (flashHistory[i].brightness == 0 && offTime == -1) {
00108 offTime = flashHistory[i].time - t1;
00109 }
00110 if (flashHistory[i].brightness > 0) {
00111 brightness = flashHistory[i].brightness;
00112 onTime = flashHistory[i].time - t1;
00113 }
00114 }
00115
00116
00117 if ((offTime < 0 || onTime < 0) && (b1 == 0)) return;
00118
00119 if (b1 > 0) {
00120 if (b2 == 0) {
00121
00122 f["flash.brightness"] = b1;
00123 f["flash.duration"] = offTime;
00124 f["flash.start"] = 0;
00125 f["flash.peak"] = offTime/2;
00126 } else {
00127
00128 f["flash.brightness"] = (b1+b2)/2;
00129 f["flash.duration"] = t2-t1;
00130 f["flash.start"] = 0;
00131 f["flash.peak"] = (t2-t1)/2;
00132 }
00133 } else {
00134 if (b2 > 0) {
00135
00136 int duration = (t2-t1) - onTime;
00137 f["flash.brightness"] = b2;
00138 f["flash.duration"] = duration;
00139 f["flash.start"] = onTime;
00140 f["flash.peak"] = onTime + duration/2;
00141 } else {
00142
00143 if (onTime >= 0) {
00144
00145 f["flash.brightness"] = brightness;
00146 f["flash.duration"] = offTime - onTime;
00147 f["flash.start"] = onTime;
00148 f["flash.peak"] = onTime + (offTime - onTime)/2;
00149 } else {
00150
00151 }
00152 }
00153 }
00154
00155
00156
00157 }
00158
00159 float Flash::getBrightness(Time t) {
00160 for (size_t i = 0; i < flashHistory.size(); i++) {
00161 if (t > flashHistory[i].time) {
00162 return flashHistory[i].brightness;
00163 }
00164 }
00165
00166
00167 error(Event::FlashHistoryError, "Flash brightness at time %d %d is unknown", t.s(), t.us());
00168 return std::numeric_limits<float>::quiet_NaN();
00169 }
00170
00171 }
00172 }