apps/autoexposure/aexp_corr.c

Go to the documentation of this file.
00001 /*!***************************************************************************
00002 *! FILE NAME  : aexp_corr.c
00003 *! DESCRIPTION: Autoexposure part of the autoexposure/white balance/hdr daemon
00004 *! Copyright (C) 2008 Elphel, Inc.
00005 *! -----------------------------------------------------------------------------**
00006 *!  This program is free software: you can redistribute it and/or modify
00007 *!  it under the terms of the GNU General Public License as published by
00008 *!  the Free Software Foundation, either version 3 of the License, or
00009 *!  (at your option) any later version.
00010 *!
00011 *!  This program is distributed in the hope that it will be useful,
00012 *!  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 *!  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 *!  GNU General Public License for more details.
00015 *!
00016 *!  You should have received a copy of the GNU General Public License
00017 *!  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00018 *! -----------------------------------------------------------------------------**
00019 *!
00020 *!  $Log: aexp_corr.c,v $
00021 *!  Revision 1.1.1.1  2008/11/27 20:04:01  elphel
00022 *!
00023 *!
00024 *!  Revision 1.2  2008/11/18 19:30:16  elphel
00025 *!  Added initialization of the "next" frame - otherwise it wait _very_ long if the camera frame number is reset
00026 *!
00027 *!  Revision 1.1  2008/11/15 23:08:24  elphel
00028 *!  8.0.alpha17 - split autoexposure source file
00029 *!
00030 *!
00031 */ 
00032 
00033 #include "autoexposure.h"
00034 void initAexpCorr(void) {
00035   GLOBALPARS(G_NEXT_AE_FRAME)=0; 
00036 }
00046 
00047 
00054 //   return gammaReverse (perc_frac);
00055 
00056 int aexpCorr(int color, int frame, int target_frame) {
00057 //  int target_frame=frame+EXPOS_AHEAD;
00058   int rslt;
00059 //  unsigned long write_data[6]; 
00060   unsigned long write_data[4]; 
00061   short * ae_err;
00062   int frac; //,frac_recover;
00063   int level,level_gamma; //,num_pix;
00064   int perc;
00065   int old_vexpos;
00066   int new_vexpos;
00067   float fvexpos;
00068   int error_thresh;
00069   int max_vexpos;
00070   int dim;
00071   int diff;
00072 //  int adiff,large_diff;
00073   int target_frame8=target_frame & PARS_FRAMES_MASK;
00074   int ae_period_change=framePars[target_frame8].pars[P_AE_PERIOD] & 0xff; 
00075   int ae_period_nochange=(framePars[target_frame8].pars[P_AE_PERIOD] >> 8 ) & 0xff; 
00076   int ae_dont_sync=(framePars[target_frame8].pars[P_AE_PERIOD] & 0x10000); 
00077   int i, aerr;
00078   
00079   if (!ae_period_change) ae_period_change=DEFAULT_AE_PERIOD_CHANGE;
00080   if (!ae_period_nochange) ae_period_nochange=DEFAULT_AE_PERIOD_NOCHANGE;
00081 //  unsigned long overexp_scale;
00082   if (!framePars[target_frame & PARS_FRAMES_MASK].pars[P_AUTOEXP_ON]) {
00083     GLOBALPARS(G_NEXT_AE_FRAME)=frame+ae_period_change;
00084     return 0; 
00085   }
00086   if (GLOBALPARS(G_NEXT_AE_FRAME)>frame) return 0; 
00087 
00088   ae_err= (short *) &(GLOBALPARS(G_AE_INTEGERR));
00089   MDF3(fprintf(stderr,"ae_err[0]=0x%04x, ae_err[1]=0x%04x\n",(int)ae_err[0],(int)ae_err[1])); 
00090 
00091   frac=framePars[target_frame & PARS_FRAMES_MASK].pars[P_AEXP_FRACPIX];
00092 //  level=framePars[target_frame & PARS_FRAMES_MASK].pars[P_AEXP_LEVEL];
00094   dim=(GLOBALPARS((color>1)?G_HIST_DIM_23:G_HIST_DIM_01) >> ((color & 1)? 16 : 0)) & 0xffff;
00096   perc=getPercentile(frame-1,color, frac, 1 << color); 
00097 //      MDF2(fprintf(stderr,"got histogram for frame: 0x%lx,  NOW: 0x%lx\n",histogram_cache[hist_index].frame, GLOBALPARS(G_THIS_FRAME)));
00098   if (histogram_cache[hist_index].frame < (frame-1)) { 
00099     GLOBALPARS(G_NEXT_AE_FRAME)=frame+1;
00100     if (ae_dont_sync) return 0; 
00101 
00102     for (i=0; i<8; i++) {
00103       frame++;
00104       MDF3(fprintf(stderr,"Skipping frame trying to synchronize, frame will be 0x%x\n",frame));
00105       lseek(fd_fparmsall, frame +LSEEK_FRAME_WAIT_ABS, SEEK_END);
00106       this_frame=frame;
00107       perc=getPercentile(frame-1,color, frac, 1 << color); 
00108       if (histogram_cache[hist_index].frame == (frame-1)) break;
00109     }
00110     if (histogram_cache[hist_index].frame < (frame-1)) { 
00111       GLOBALPARS(G_NEXT_AE_FRAME)=frame+1;
00112       return 0; 
00113     }
00114   }
00115   level_gamma=framePars[target_frame & PARS_FRAMES_MASK].pars[P_AEXP_LEVEL];
00117   level=gammaReverse (level_gamma);
00118   MDF3(fprintf(stderr,"->>> frame=0x%x, target_frame=0x%x,dim=0x%04x, frac=0x%04x, level=0x%x,level_gamma=0x%x, perc=0x%04x\n",frame,target_frame,dim,frac,level,level_gamma,perc));
00119   if (perc <0) {
00120      GLOBALPARS(G_NEXT_AE_FRAME)=frame+ae_period_change;
00121      return -1; 
00122   }
00126 //  if (perc > ((level+0xffff)>>1)) {
00127   if ((perc > ((level_gamma+0x1ffff)>>2))&& (perc>0xf000) ) {
00128      aex_recover_cntr++; 
00129 
00130 
00131      MDF1(fprintf(stderr,"--- Triggered overexposure recovery:perc=0x%x, level_gamma=0x%x,aex_recover_cntr=0x%x\n",perc,level_gamma,aex_recover_cntr));
00132 /*
00135      num_pix=histogram_cache[hist_index].cumul_hist[255 + (color<<8)];
00136 //     level_gamma=gamma_cache[gamma_index].direct[level>>8]; /// truncating , no interpolation
00137      frac_recover= (((long long )histogram_cache[hist_index].cumul_hist[(level_gamma>>8) + (color<<8)])<<16)/num_pix;
00138      if (frac_recover>frac) {
00139        MDF1(fprintf(stderr,"BUG in overexp recovery frac=0x%04x, frac_recover=0x%04x,\n",frac,frac_recover));
00140        frac_recover=frac;
00141      } //autoexposure.c:714:aexpCorr: level_gamma=0xa000, num_pix=0x3ffff, frac=0xf000, frac_recover=0x0000,
00142      MDF3(fprintf(stderr,"level_gamma=0x%x, num_pix=0x%x, frac=0x%04x, frac_recover=0x%04x,\n",level_gamma, num_pix,frac,frac_recover));
00143      level=(((level >> 8)*frac_recover)/frac)<<8;
00144      frac=frac_recover;
00145      perc=getPercentile(frame-1,color, frac, 0); 
00146      MDF3(fprintf(stderr,"*** frac=0x%04x, level=0x%x,perc=0x%04x\n",frac,level,perc));
00147 */
00148   } else { 
00149     aex_recover_cntr=0;
00150   }
00151 
00152 
00153   old_vexpos= get_imageParamsThatValid(P_VEXPOS, frame-1);
00154   if (old_vexpos <0) {
00155     GLOBALPARS(G_NEXT_AE_FRAME)=frame+ae_period_change;
00156     return -2; 
00157   }
00158   if (old_vexpos==1) {
00159     fvexpos=old_vexpos;
00160     new_vexpos= (fvexpos*level)/perc;
00161   } else {
00162     fvexpos=(old_vexpos-1);
00163     if (perc < (dim>>1)) { 
00164       new_vexpos= (fvexpos*level)/perc;
00165     } else {
00166       new_vexpos= (fvexpos*(level-dim))/(perc-dim);
00167     }
00168     if (aex_recover_cntr > 3) { 
00169       MDF1(fprintf(stderr,">>>> Reducing new_vexpos twice\n"));
00170       new_vexpos=(new_vexpos>>1)+1;
00171     }
00172   }
00173 
00174 
00175   MDF3(fprintf(stderr,"old_vexpos=0x%x, new_vexpos=0x%x,\n",old_vexpos,new_vexpos));
00177   max_vexpos= framePars[target_frame & PARS_FRAMES_MASK].pars[P_AUTOEXP_EXP_MAX]; 
00178   if (!max_vexpos) max_vexpos=0x4000; 
00179   if (new_vexpos < 1) new_vexpos=1;
00180   else {
00181     if (new_vexpos > max_vexpos) new_vexpos=max_vexpos;
00182     if (new_vexpos > (old_vexpos*4)) new_vexpos=(old_vexpos*4);
00183   }
00184   diff=poorLog(new_vexpos) - poorLog(old_vexpos);
00185   ae_err[0]+=diff;
00186 //  adiff=abs(diff);
00187   MDF3(fprintf(stderr,"old_vexpos=0x%x, new_vexpos=0x%x, poorLog(new_vexpos)=0x%x,  poorLog(old_vexpos)=0x%x, diff=%d, ae_err=%d\n", old_vexpos, new_vexpos, poorLog(new_vexpos), poorLog(old_vexpos), diff, ae_err[0]));
00188   error_thresh=framePars[target_frame & PARS_FRAMES_MASK].pars[P_AE_THRESH];
00189   aerr=abs (ae_err[0]);
00190   if (aerr>error_thresh) aerr=error_thresh;
00191   new_vexpos=(old_vexpos*(error_thresh-aerr)+new_vexpos*aerr)/error_thresh;
00192   if (new_vexpos==old_vexpos) {
00193      MDF3(fprintf(stderr,"No correction: thrshold=%d, aerr=%d\n",error_thresh,aerr));  
00194      GLOBALPARS(G_NEXT_AE_FRAME)=frame+ae_period_nochange; 
00195      return 0; 
00196   }
00197   ae_err[0]=0; 
00198 
00199 
00200   write_data[0]= FRAMEPARS_SETFRAME;
00201   write_data[1]= target_frame;
00202   write_data[2]= P_VEXPOS; // | FRAMEPAIR_FORCE_NEWPROC ?
00203   write_data[3]= new_vexpos;
00204 //  write_data[4]= P_HISTRQ_Y; /// will request once histogtram for that frame
00205 //  write_data[5]= 1;
00206   rslt=write(fd_fparmsall, write_data, sizeof(write_data));
00207   if (rslt < sizeof(write_data)) return -errno;
00208   GLOBALPARS(G_NEXT_AE_FRAME)=frame+ae_period_change;
00209   return 1;
00210 }
00211 

Generated on Fri Nov 28 00:06:21 2008 for elphel by  doxygen 1.5.1