apps/autoexp/autoexp.c

Go to the documentation of this file.
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    /* 50% */
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 /* start exposure value */
00043 //unsigned long current_exp = 100;
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 //      int i, j;
00058         unsigned long *m;
00059 //      unsigned long s;
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 //float t_skip = state.skip_t;
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         /* process cycle */
00093         while(1) {
00094                 r = ioctl(fd, _IO(IOC_HIST_GET, 0x00), &autoexp_buf);
00095                 if(r == REZ_HIST_CONF) {
00096 //syslog(LOG_ALERT, "REZ_HIST_CONF\r\n");
00097                         if(autoexp_buf.exp_max != HIST_NOT_CHANGE) {
00098                                 state.exp_max = autoexp_buf.exp_max;
00099 //printf("HIST_CONF: state.exp_max = %lu\r\n", state.exp_max);
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 //syslog(LOG_ALERT, "state.s_index == %d\r\n", state.s_index);
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 //syslog(LOG_ALERT, "state.s_percent == %d\r\n", state.s_percent);
00117                         }
00118                         if(autoexp_buf.skip_pmin != HIST_NOT_CHANGE) {
00119                                 state.skip_pmin = autoexp_buf.skip_pmin;
00120 //syslog(LOG_ALERT, "state.skip_pmin == %d\r\n", state.skip_pmin);
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 //syslog(LOG_ALERT, "state.skip_pmax == %d\r\n", state.skip_pmax);
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 //syslog(LOG_ALERT, "state.skip_t == %d\r\n", state.skip_t);
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                 /* analyze histogramm */
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 //syslog(LOG_ALERT, "HIST_SIZE == %d; 0 == 0x%04X, 1 == 0x%04X, 254 == 0x%04X, 255 == 0x%04X\r\n", HIST_SIZE, gamma[0], gamma[1], gamma[254], gamma[255]);
00188 //syslog(LOG_ALERT, "map == 0x%08X, gamma == 0x%08X\r\n", map, gamma);
00189                 m = (unsigned long *)map;
00190                 /* summ of all 4 tables... */
00191 //              sq = autoexp_buf.width * autoexp_buf.height;
00192 //              sq = autoexp_set.width * autoexp_set.height;
00193                 sq = state.width * state.height;
00194 //              if(autoexp_buf.exp != HIST_NOT_CHANGE)
00195 //                      state.exp = autoexp_buf.exp;
00196 //printf("width == %lu\r\n", autoexp_buf.width);
00197 //printf("height == %lu\r\n", autoexp_buf.height);
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 //                      if(state.exp > state.exp_max) {
00212                         if(d > state.exp_max) {
00213 //                              state.exp = autoexp_set.exp = state.exp_max;
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 //                      state.exp = autoexp_set.exp = d;
00225                 }
00226                 /* send log message in driver */
00227                 if(flag == 1) {
00228                         if(state.s_index != 0 && state.s_percent != 0) {
00229 //                              stable_flag = 1;
00230                                 /* check percent delta */
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 //                              if(s > pmin_high || s < pmin_low) {
00243                                 if(f) {
00244                                         /* check value delta */
00245                                         if(abs(d_prev - d) > state.skip_t) {
00246 //                                              f = 0;
00247                                                 /* check max step */
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                 /* set changes */
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 //      return indx;
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         /* normalize */
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                 // overexposure...
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 //                              r = 254.0 / r;
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 //syslog(LOG_ALERT, "r = %.2f\r\n", r);
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 //      static int c = 0;
00380 
00381         p = state.s_percent;
00382         p /= 100.0;
00383 //      g = (unsigned short *)((void *)t + 256 * 4 * 4 + 256 * 4 * 2);
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 //      i = g[state.s_index + 256] >> 8;
00391         i = g[state.s_index + 256] >> 8;
00392         v = h[i];
00393         v /= s;
00394         v *= 100.0; // current percent in interesting index
00395         _p = p;
00396         _p /= 100.0;
00397         _p *= s;
00398         value = _p; // needed sum in "ideal" index
00399 //      i = g[state.s_index + 256] >> 8;
00400 //if(c < 20)
00401 //      syslog(LOG_ALERT, "in index (%d): v == %.2f, p == %.2f\r\n", i, v, p);
00402         autoexp_log.n_index = i;
00403         autoexp_log.n_percent = v * 100;
00404         if(v > p) {
00405                 /* set up */
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 //                              return r;
00419                                 
00420                                 goto ret;
00421                         }
00422                 }
00423                 r = 1.0;
00424         } else {
00425                 /* set down */
00426                 if(h[254] > value) {
00427                         /* find index and set it */
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                                         /* log data */
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         c++;
00455         if(c < 20)
00456                 syslog(LOG_ALERT, "in index: v == %.2f, ret == %.2f\r\n", v, r);
00457         else
00458                 c = 25;
00459 */
00460 //      if(r != 1.0) {
00461 //              syslog(LOG_ALERT, "in index: v == %.2f, p == %.2f, ret == %.2f, value == %d, h[%d] == %d, h[254] == %d\r\n", v, p, r, value, j, h[j], h[254]);
00462 //      }
00463         if(r < 0.05)
00464                 r = 0.05;
00465         return r;
00466 }

Generated on Thu Aug 7 16:18:58 2008 for elphel by  doxygen 1.5.1