00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <unistd.h>
00004 #include <sys/ioctl.h>
00005 #include <sys/types.h>
00006 #include <sys/stat.h>
00007 #include <fcntl.h>
00008
00009 #include <sys/mman.h>
00010
00011 #include <asm/elphel/hist.h>
00012 #include <asm/elphel/autoexp.h>
00013 #include <asm/elphel/c313a.h>
00014 #include <syslog.h>
00015
00016 #define MAX_OVEREXP 5000
00017 #define MAX_WIDTH 100
00018 #define MAX_HEIGHT 100
00019 #define MIN_WIDTH 5
00020 #define MIN_HEIGHT 5
00021 #define MAX_LEFT 100
00022 #define MAX_TOP 100
00023 #define MAX_S_INDEX 255
00024 #define MAX_S_PERCENT 10000
00025
00026 #define PMAX_MAX 9000
00027 #define PMAX_MIN 5000
00028
00029 struct autoexp_t state = {
00030 .s_index = 0,
00031 .s_percent = 0,
00032 .exp = 100,
00033 .skip_pmin = 500,
00034 .skip_pmax = 5000,
00035 .skip_t = 2,
00036 };
00037
00038
00039 struct autoexp_t autoexp_set;
00040 struct autoexp_log_t autoexp_log;
00041
00042
00043
00044
00045 #define HIST_SIZE (256 * 4 * 4 + 256 * 2)
00046 unsigned short *gamma;
00047
00048 float hist_analyze(unsigned long *t, unsigned long sq);
00049 float hist_analyze_percent(unsigned long *t, unsigned long sq);
00050 void hist_stat();
00051
00052 int skip_first_frames = 0;
00053
00054 int main(void) {
00055 int fd;
00056 void *map;
00057
00058 unsigned long *m;
00059
00060 unsigned long sq;
00061 float d;
00062 float s;
00063 int r;
00064 struct autoexp_t autoexp_buf;
00065 int flag = 0;
00066
00067 float pmin_low = state.skip_pmin;
00068 pmin_low /= 100.0;
00069 pmin_low /= 100.0;
00070 float pmin_high = 1.0 + pmin_low;
00071 pmin_low = 1.0 - pmin_low;
00072 float d_prev = 0;
00073
00074 int prev_change_max = 0;
00075 int stable_flag = 0;
00076 int f = 0;
00077 float pmax_low = state.skip_pmax;
00078 pmax_low /= 100.0;
00079 pmax_low /= 100.0;
00080 float pmax_high = 1.0 + pmax_low;
00081 pmax_low = 1.0 - pmax_low;
00082 int prev_perc_min = 0;
00083
00084 openlog("autoexp", 0, 0);
00085
00086 fd = open(DEV_HIST_NAME, O_RDWR);
00087 if(fd <= 0) {
00088 printf("Aiee! can't open %s - may be device busy or not exist...\r\n", DEV_HIST_NAME);
00089 return -1;
00090 }
00091
00092
00093 while(1) {
00094 r = ioctl(fd, _IO(IOC_HIST_GET, 0x00), &autoexp_buf);
00095 if(r == REZ_HIST_CONF) {
00096
00097 if(autoexp_buf.exp_max != HIST_NOT_CHANGE) {
00098 state.exp_max = autoexp_buf.exp_max;
00099
00100 }
00101 if(autoexp_buf.overexp_max != HIST_NOT_CHANGE) {
00102 state.overexp_max = autoexp_buf.overexp_max;
00103 if(state.overexp_max > MAX_OVEREXP)
00104 state.overexp_max = MAX_OVEREXP;
00105 }
00106 if(autoexp_buf.s_index != HIST_NOT_CHANGE) {
00107 state.s_index = autoexp_buf.s_index;
00108 if(state.s_index > MAX_S_INDEX)
00109 state.s_index = MAX_S_INDEX;
00110
00111 }
00112 if(autoexp_buf.s_percent != HIST_NOT_CHANGE) {
00113 state.s_percent = autoexp_buf.s_percent;
00114 if(state.s_percent > MAX_S_PERCENT)
00115 state.s_percent = MAX_S_PERCENT;
00116
00117 }
00118 if(autoexp_buf.skip_pmin != HIST_NOT_CHANGE) {
00119 state.skip_pmin = autoexp_buf.skip_pmin;
00120
00121 pmin_low = state.skip_pmin;
00122 pmin_low /= 100.0;
00123 pmin_low /= 100.0;
00124 pmin_high = 1.0 + pmin_low;
00125 pmin_low = 1.0 - pmin_low;
00126 }
00127 if(autoexp_buf.skip_pmax != HIST_NOT_CHANGE) {
00128 state.skip_pmax = autoexp_buf.skip_pmax;
00129 if(state.skip_pmax > PMAX_MAX)
00130 state.skip_pmax = PMAX_MAX;
00131 if(state.skip_pmax < PMAX_MIN)
00132 state.skip_pmax = PMAX_MIN;
00133
00134 pmax_low = state.skip_pmax;
00135 pmax_low /= 100.0;
00136 pmax_low /= 100.0;
00137 pmax_high = 1.0 + pmax_low;
00138 pmax_low = 1.0 - pmax_low;
00139 }
00140 if(autoexp_buf.skip_t != HIST_NOT_CHANGE) {
00141 state.skip_t = autoexp_buf.skip_t;
00142
00143 }
00144 if(autoexp_buf.width != HIST_NOT_CHANGE) {
00145 state.width = autoexp_buf.width;
00146 if(state.width > MAX_WIDTH)
00147 state.width = MAX_WIDTH;
00148 if(state.width < MIN_WIDTH)
00149 state.width = MIN_WIDTH;
00150 flag = 1;
00151 }
00152 if(autoexp_buf.height != HIST_NOT_CHANGE) {
00153 state.height= autoexp_buf.height;
00154 if(state.height > MAX_HEIGHT)
00155 state.height = MAX_HEIGHT;
00156 if(state.height < MIN_HEIGHT)
00157 state.height = MIN_HEIGHT;
00158 flag = 1;
00159 }
00160 if(autoexp_buf.left != HIST_NOT_CHANGE) {
00161 state.left= autoexp_buf.left;
00162 if(state.left > MAX_LEFT)
00163 state.left = MAX_LEFT;
00164 flag = 1;
00165 }
00166 if(autoexp_buf.top != HIST_NOT_CHANGE) {
00167 state.top= autoexp_buf.top;
00168 if(state.top > MAX_TOP)
00169 state.top = MAX_TOP;
00170 flag = 1;
00171 }
00172 if(flag) {
00173 flag = 0;
00174 autoexp_set.width = state.width;
00175 autoexp_set.height = state.height;
00176 autoexp_set.left = state.left;
00177 autoexp_set.top = state.top;
00178 autoexp_set.exp = 0;
00179
00180 ioctl(fd, _IO(IOC_HIST_SET, 0x00), &autoexp_set);
00181 }
00182 continue;
00183 }
00184
00185 map = mmap(NULL, TABLES_LEN, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, fd, 0);
00186 gamma = (unsigned short *)(map + 256 * 4 * 4);
00187
00188
00189 m = (unsigned long *)map;
00190
00191
00192
00193 sq = state.width * state.height;
00194
00195
00196
00197
00198 if(sq == 0) {
00199 munmap(map, HIST_SIZE);
00200 continue;
00201 }
00202 if(state.s_index == 0 || state.s_percent == 0)
00203 d = hist_analyze(m, sq);
00204 else
00205 d = hist_analyze_percent(m, sq);
00206 munmap(map, HIST_SIZE);
00207 s = d;
00208 flag = 0;
00209 if(d == 1.0) {
00210 d = state.exp;
00211
00212 if(d > state.exp_max) {
00213
00214 d = state.exp_max;
00215 flag = 1;
00216 }
00217 } else {
00218 flag = 1;
00219 d *= state.exp;
00220 if(d > state.exp_max)
00221 d = state.exp_max;
00222 if(d < 1)
00223 d = 1;
00224
00225 }
00226
00227 if(flag == 1) {
00228 if(state.s_index != 0 && state.s_percent != 0) {
00229
00230
00231 f = 0;
00232 if(s <= pmin_high && s >= pmin_low) {
00233 if(prev_perc_min)
00234 f = 0;
00235 else
00236 f = 1;
00237 prev_perc_min = 1;
00238 } else {
00239 prev_perc_min = 0;
00240 f = 1;
00241 }
00242
00243 if(f) {
00244
00245 if(abs(d_prev - d) > state.skip_t) {
00246
00247
00248 if(s > pmax_high || s < pmax_low) {
00249 if(prev_change_max) {
00250 f = 1;
00251 } else {
00252 f = 0;
00253 }
00254 prev_change_max = 1;
00255 } else {
00256 f = 1;
00257 prev_change_max = 0;
00258 }
00259 if(f) {
00260 stable_flag = 0;
00261 d_prev = d;
00262 state.exp = autoexp_set.exp = d;
00263 ioctl(fd, _IO(IOC_HIST_SET, 0x00), &autoexp_set);
00264 autoexp_log.s_index = state.s_index;
00265 autoexp_log.s_percent = state.s_percent;
00266 autoexp_log.t_scale = s * 0x10000;
00267 autoexp_log.t_value = state.exp;
00268 ioctl(fd, _IO(IOC_HIST_SET_LOG, 0x00), &autoexp_log);
00269 } else {
00270 stable_flag = 1;
00271 }
00272 }
00273 }
00274 } else {
00275 d_prev = d;
00276 state.exp = autoexp_set.exp = d;
00277 ioctl(fd, _IO(IOC_HIST_SET, 0x00), &autoexp_set);
00278 }
00279 }
00280
00281 }
00282
00283 close(fd);
00284 return 0;
00285 }
00286
00287 static unsigned long inline _sum(unsigned long *t, int i) {
00288 return (t[i + 256 * 0] + t[i + 256 * 1] + t[i + 256 * 2] + t[i + 256 * 3]);
00289 }
00290
00291 float normalize_gamma(int indx) {
00292 float r = 255.0;
00293 unsigned short g;
00294 int low;
00295 low = gamma[0] >> 8;
00296
00297 g = gamma[indx];
00298 r = g & 0xFF;
00299 r /= 256.0;
00300 r += g >> 8;
00301 r -= low;
00302 r *= 256.0 / (256.0 - (float)low);
00303 return r;
00304
00305 }
00306
00307 float hist_analyze(unsigned long *t, unsigned long sq) {
00308 unsigned long s = 0;
00309 float r = 1.0;
00310 int i;
00311 float over;
00312 unsigned long l_255;
00313 unsigned long s_255;
00314 unsigned long s_254;
00315 unsigned long s_253;
00316 unsigned long sc;
00317 int flag;
00318
00319 sq = 0;
00320 for(i = 0; i < 1024; i++) {
00321 sq += t[i];
00322 }
00323
00324 over = state.overexp_max;
00325 over /= 100.0;
00326 over /= 100.0;
00327 over *= sq;
00328 l_255 = over;
00329
00330 s_255 = _sum(t, 255);
00331 s_254 = _sum(t, 254) + s_255;
00332 s_253 = _sum(t, 253) + s_254;
00333
00334 r = 1.0;
00335 if(s_255 >= l_255) {
00336
00337 r = s_255;
00338 r /= (l_255 / 8);
00339 r = (255.0 - r) / 255.0;
00340 if(r < 0.5)
00341 r = 0.5;
00342 goto out;
00343 }
00344 if(s_254 < l_255) {
00345 sc = 0;
00346 flag = 0;
00347 for(i = 255; i > 120; i--) {
00348 s = _sum(t, i);
00349 sc += s;
00350 if(sc >= l_255) {
00351 flag = 1;
00352 r = normalize_gamma(i + 1);
00353
00354 r = 252.0 / r;
00355 if(r < 1.0)
00356 r = 1.0;
00357 break;
00358 }
00359 }
00360 if(flag == 0)
00361 r = 2.0;
00362 if(r <= 1.02 && r > 1.0)
00363 r = 1.0;
00364 }
00365 out:
00366
00367 return r;
00368 }
00369
00370 float hist_analyze_percent(unsigned long *t, unsigned long sq) {
00371 unsigned long h[256];
00372 unsigned long long s;
00373 unsigned short *g;
00374 unsigned long value;
00375 float v;
00376 float p, _p;
00377 int i, j = 0;
00378 float r = 1.0;
00379
00380
00381 p = state.s_percent;
00382 p /= 100.0;
00383
00384 g = (unsigned short *)((void *)t + 256 * 4 * 4);
00385 h[0] = t[0] + t[256] + t[512] + t[768];
00386 for(i = 1; i < 256; i++) {
00387 h[i] = h[i - 1] + t[i] + t[i + 256] + t[i + 512] + t[i + 768];
00388 }
00389 s = h[255];
00390
00391 i = g[state.s_index + 256] >> 8;
00392 v = h[i];
00393 v /= s;
00394 v *= 100.0;
00395 _p = p;
00396 _p /= 100.0;
00397 _p *= s;
00398 value = _p;
00399
00400
00401
00402 autoexp_log.n_index = i;
00403 autoexp_log.n_percent = v * 100;
00404 if(v > p) {
00405
00406 for(j = 8; j < i; j++) {
00407 if(h[j] >= value) {
00408 r = g[j] & 0xFF;
00409 r /= 256.0;
00410 r += (g[j] >> 8);
00411 r = ((float)state.s_index) / r;
00412 autoexp_log.n_index = g[j] >> 8;
00413 _p = h[j];
00414 _p *= 100;
00415 _p /= s;
00416 _p *= 100;
00417 autoexp_log.n_percent = _p;
00418
00419
00420 goto ret;
00421 }
00422 }
00423 r = 1.0;
00424 } else {
00425
00426 if(h[254] > value) {
00427
00428 for(j = 254; j > i; j--) {
00429 if(h[j] <= value) {
00430 r = g[j] & 0xFF;
00431 r /= 256.0;
00432 r += (g[j] >> 8);
00433
00434 autoexp_log.n_index = g[j] >> 8;
00435 _p = h[j];
00436 _p *= 100;
00437 _p /= s;
00438 _p *= 100;
00439 autoexp_log.n_percent = _p;
00440 r = ((float)state.s_index) / r;
00441 goto ret;
00442 }
00443 }
00444 r = 1.0;
00445 } else {
00446 autoexp_log.n_index = 255;
00447 autoexp_log.n_percent = 10000;
00448 r = v / p;
00449 }
00450 }
00451
00452 ret:
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463 if(r < 0.05)
00464 r = 0.05;
00465 return r;
00466 }