Home | History | Annotate | Download | only in src
      1 
      2 /*
      3  * Copyright (C) Texas Instruments - http://www.ti.com/
      4  *
      5  * This library is free software; you can redistribute it and/or
      6  * modify it under the terms of the GNU Lesser General Public
      7  * License as published by the Free Software Foundation; either
      8  * version 2.1 of the License, or (at your option) any later version.
      9  *
     10  *
     11  * This library is distributed in the hope that it will be useful,
     12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14  * Lesser General Public License for more details.
     15  *
     16  *
     17  * You should have received a copy of the GNU Lesser General Public
     18  * License along with this library; if not, write to the Free Software
     19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     20  */
     21 
     22 #ifdef __PERF_CUSTOMIZABLE__
     23 
     24     #define __PERF_RT_C__
     25 
     26     #include "perf_config.h"
     27     #include "perf.h"
     28     #include "perf_rt.h"
     29     #include "math.h"
     30 
     31 /* ============================================================================
     32    DEBUG RT METHODS
     33 ============================================================================ */
     34 
     35 #define MAX_RATES_TRACKED   10
     36 #define MAX_GRANULARITY     15
     37 #define MIN_FRAMES_FOR_RATE 10
     38 
     39 static int uptime_started = 0;
     40 
     41 static void init_delay(PERF_RTdata_delay *dDelay, long n0)
     42 {
     43     dDelay->xx = dDelay->x = 0;
     44     dDelay->n = n0;
     45 }
     46 
     47 PERF_RT_Private *
     48 PERF_RT_create(PERF_Private *perf, PERF_Config *config,
     49                PERF_MODULETYPE eModule)
     50 {
     51     char *fOutFile = NULL;
     52     FILE *fOut = NULL;
     53 
     54     /* check if we support this component */
     55     if (perf->ulID != PERF_FOURS("CAM_") && perf->ulID != PERF_FOURS("CAMT") &&
     56         perf->ulID != PERF_FOURS("VP__") && perf->ulID != PERF_FOURS("VP_T") &&
     57         perf->ulID != PERF_FOURS("VD__") && perf->ulID != PERF_FOURS("VD_T") &&
     58         perf->ulID != PERF_FOURS("VE__") && perf->ulID != PERF_FOURS("VE_T"))
     59     {
     60         /* if we don't support this component, we don't create the real-time
     61            interface */
     62         return (NULL);
     63     }
     64 
     65     PERF_RT_Private *me =
     66     perf->cip.pRT = malloc(sizeof(PERF_RT_Private));
     67 
     68     if (me)
     69     {
     70         int succeed = 1;
     71 
     72         /* we track steady state on the component thread only */
     73         me->needSteadyState = (perf->ulID & 0xff) == 'T';
     74         me->steadyState = 0;
     75 
     76         /* allocate rate tracking structures */
     77         me->maxDRate = MAX_RATES_TRACKED;
     78         me->dRate = malloc(sizeof(PERF_RTdata_rate) * me->maxDRate);
     79         succeed = succeed && me->dRate;
     80 
     81         me->decoder = (perf->ulID == PERF_FOURS("VD__") || perf->ulID == PERF_FOURS("VD_T"));
     82         me->encoder = (perf->ulID == PERF_FOURS("VE__") || perf->ulID == PERF_FOURS("VE_T"));
     83         me->nDRate = 0;
     84 
     85         /* allocate shot-to-shot tracking structures */
     86         if (succeed && perf->ulID == PERF_FOURS("CAMT"))
     87         {
     88             me->dSTS = malloc(sizeof(PERF_RTdata_sts));
     89             succeed = succeed && me->dSTS;
     90             if (me->dSTS)
     91             {
     92                 init_delay(&me->dSTS->dBurst, -1);   /* no first timestamp yet */
     93                 init_delay(&me->dSTS->dABurst, 0);
     94                 init_delay(&me->dSTS->dBurst2, 0);
     95                 init_delay(&me->dSTS->dABurst2, 0);
     96                 init_delay(&me->dSTS->dSingle, -1);  /* no first timestamp yet */
     97                 me->dSTS->size_max = me->dSTS->size_min = me->dSTS->capturing = 0;
     98             }
     99         }
    100         else
    101         {
    102             me->dSTS = NULL;
    103         }
    104 
    105         /* allocate uptime tracking structures */
    106 
    107         /* :NOTE: for now we restrict creations of uptime to steady state
    108             only */
    109         if (succeed && !uptime_started && me->needSteadyState &&
    110             !(perf->uMode & PERF_Mode_Replay))
    111         {
    112             me->dUptime = malloc(sizeof(PERF_RTdata_uptime));
    113             succeed = succeed && me->dUptime;
    114 
    115             if (succeed)
    116             {
    117                 uptime_started = 1;
    118                 me->dUptime->measuring = 0;
    119                 me->dUptime->last_idletime = me->dUptime->last_uptime = 0;
    120                 me->dUptime->start_idletime = me->dUptime->start_uptime = 0;
    121                 me->dUptime->success = 1;
    122                 me->dUptime->xx = me->dUptime->x = me->dUptime->n = 0;
    123                 TIME_GET(me->dUptime->last_reporting);
    124             }
    125         }
    126         else
    127         {
    128             me->dUptime = NULL;
    129         }
    130 
    131         /* configuration */
    132         me->summary     = config->rt_summary != 0;
    133         me->debug       = config->rt_debug & 0x1FF;
    134         me->detailed    = (config->rt_detailed > 2) ? 2 : (int) config->rt_detailed;
    135 
    136         me->granularity = (config->rt_granularity < 1) ? 1 :
    137                           (config->rt_granularity > MAX_GRANULARITY) ?
    138                           MAX_GRANULARITY : (long) config->rt_granularity;
    139         me->granularity *= 1000000;  /* convert to microsecs */
    140         TIME_COPY(me->first_time, perf->time);
    141 
    142         /* if we do not care about detailed statistics, only report significant
    143            statistics for each component */
    144         if (succeed && !me->detailed)
    145         {
    146             /* VP_T - display rate */
    147             if (perf->ulID == PERF_FOURS("VP_T"))
    148             {
    149                 me->only_moduleandflags = PERF_FlagSending | PERF_FlagFrame | PERF_ModuleHardware;
    150             }
    151             /* VD_T - decode rate */
    152             else if (perf->ulID == PERF_FOURS("VD_T"))
    153             {
    154                 me->only_moduleandflags = PERF_FlagSending | PERF_FlagFrame | PERF_ModuleLLMM;
    155             }
    156             /* VE_T - encode rate */
    157             else if (perf->ulID == PERF_FOURS("VE_T"))
    158             {
    159                 me->only_moduleandflags = PERF_FlagSending | PERF_FlagFrame | PERF_ModuleLLMM;
    160             }
    161             /* CAMT - capture rate */
    162             else if (perf->ulID == PERF_FOURS("CAMT"))
    163             {
    164                 me->only_moduleandflags = PERF_FlagReceived | PERF_FlagFrame | PERF_ModuleHardware;
    165             }
    166             /* otherwise, we don't care about rates */
    167             else
    168             {
    169                 free(me->dRate);
    170                 me->dRate = NULL;
    171                 me->maxDRate = 0;
    172             }
    173         }
    174 
    175         /* set up fRt file pointers */
    176         if (config->rt_file && succeed)
    177         {
    178             /* open log file unless STDOUT or STDERR is specified */
    179             if (!strcasecmp(config->rt_file, "STDOUT")) fOut = stdout;
    180             else if (!strcasecmp(config->rt_file, "STDERR")) fOut = stderr;
    181             else
    182             {
    183                 /* expand file name with PID and name */
    184                 fOutFile = (char *) malloc (strlen(config->rt_file) + 32);
    185                 if (fOutFile)
    186                 {
    187                     sprintf(fOutFile, "%s-%05lu-%08lx-%c%c%c%c.log",
    188                             config->rt_file, perf->ulPID, (unsigned long) perf,
    189                             PERF_FOUR_CHARS(perf->ulID));
    190                     fOut = fopen(fOutFile, "at");
    191 
    192                     /* free new file name */
    193                     free(fOutFile);
    194                     fOutFile = NULL;
    195                 }
    196 
    197                 /* if could not open output, set it to STDOUT */
    198                 if (!fOut) fOut = stderr;
    199             }
    200             me->fRt = fOut;
    201         }
    202 
    203         /* if we had allocation failures, free resources and return NULL */
    204         if (succeed)
    205         {
    206             perf->uMode |= PERF_Mode_RealTime;
    207         }
    208         else
    209         {
    210             PERF_RT_done(perf);
    211             me = NULL;
    212         }
    213     }
    214 
    215     return(me);
    216 }
    217 
    218 void PERF_RT_done(PERF_Private *perf)
    219 {
    220     PERF_RT_Private *me = perf->cip.pRT;
    221 
    222     /* close debug file unless stdout or stderr */
    223     if (me->fRt && me->fRt != stdout &&
    224         me->fRt != stderr) fclose(me->fRt);
    225 
    226     /* free allocated structures */
    227     free(me->dRate);   me->dRate = NULL;
    228     free(me->dUptime); me->dUptime = NULL;
    229     free(me->dSTS);    me->dSTS = NULL;
    230 
    231     /* free private structure */
    232     free(me);
    233     perf->cip.pRT = NULL;
    234 }
    235 
    236 static void get_uptime(double *uptime, double *idletime)
    237 {
    238     FILE *fUptime = fopen("/proc/uptime", "r");
    239     if (fUptime)
    240     {
    241         fscanf(fUptime, "%lg %lg", uptime, idletime);
    242         fclose (fUptime);
    243     }
    244     else
    245     {
    246         *uptime = *idletime = 0.;
    247     }
    248 }
    249 
    250 static void start_stop_uptime(PERF_RTdata_uptime *dUptime, int start)
    251 {
    252     double uptime, idletime;
    253 
    254     if (dUptime && dUptime->measuring != start)
    255     {
    256         /* add uptime since last time */
    257         get_uptime(&uptime, &idletime);
    258 
    259         /* if successful */
    260         if (dUptime->success && uptime && idletime)
    261         {
    262             dUptime->start_idletime = idletime - dUptime->start_idletime;
    263             dUptime->start_uptime = uptime - dUptime->start_uptime;
    264             dUptime->last_idletime = idletime - dUptime->last_idletime;
    265             dUptime->last_uptime = uptime - dUptime->last_uptime;
    266         }
    267         else
    268         {
    269             dUptime->start_idletime = dUptime->start_uptime = dUptime->success = 0;
    270             dUptime->last_idletime = dUptime->last_uptime = 0;
    271         }
    272 
    273         dUptime->measuring = start;
    274     }
    275 }
    276 
    277 extern char const * const PERF_ModuleTypes[];
    278 
    279 double my_sqrt(double a)
    280 {
    281     double b = (a + 1) / 2;
    282     b = (b + a/b) / 2;
    283     b = (b + a/b) / 2;
    284     b = (b + a/b) / 2;
    285     b = (b + a/b) / 2;
    286     b = (b + a/b) / 2;
    287     b = (b + a/b) / 2;
    288     return (b + a/b) / 2;
    289 }
    290 
    291 static const char *sendRecvTxt[] = {
    292         "received", "sending", "requesting", "sent",
    293     };
    294 
    295 static void print_rate_info(FILE *fOut,
    296                             unsigned long ID, PERF_MODULETYPE modulesAndFlags,
    297                             unsigned long size, long n)
    298 {
    299     unsigned long module1 = modulesAndFlags & PERF_ModuleMask;
    300     unsigned long module2 = (modulesAndFlags >> PERF_ModuleBits) & PERF_ModuleMask;
    301     int xfering  = PERF_IsXfering(modulesAndFlags);
    302     int sendIx   = (PERF_GetSendRecv(modulesAndFlags) >> 28) & 3;
    303     int sending  = PERF_IsSending(modulesAndFlags);
    304     int frame    = PERF_IsFrame  (modulesAndFlags);
    305 
    306     fprintf(fOut, "%c%c%c%c %s %ld+ %s[0x%lX]%s%s%s%s",
    307             PERF_FOUR_CHARS(ID),
    308             xfering ? "xfering" : sendRecvTxt[sendIx],
    309             n,
    310             frame ? "frames" : "buffers",
    311             size,
    312             (xfering || !sending) ? " from " : " to ",
    313             (module1 < PERF_ModuleMax ? PERF_ModuleTypes[module1] : "INVALID"),
    314             xfering ? " to " : "",
    315             xfering ? (module2 < PERF_ModuleMax ? PERF_ModuleTypes[module2] : "INVALID") : "");
    316 }
    317 
    318 void count_temporal_rate(unsigned long ID, PERF_RT_Private *me, PERF_RTdata_rate *dRate)
    319 {
    320     /* get the temporal rate */
    321     double x = (dRate->tn ? (dRate->tx ? ((1e6 * dRate->tn) / dRate->tx) : 1e6) : 0.);
    322     if (me->debug)
    323     {
    324         fprintf(me->fRt, "rtPERF: [%ld] ", TIME_DELTA(dRate->last_reporting, me->first_time)/1000000);
    325         print_rate_info(me->fRt,
    326                         ID, dRate->modulesAndFlags, dRate->size, dRate->tn);
    327 
    328         /* calculate smoothness */
    329         double s = dRate->txx ? (dRate->tx * (double) dRate->tx / dRate->txx / dRate->tn) : 1;
    330 
    331         fprintf(me->fRt, ": %.3g fps (s=%.3g)\n", x, s);
    332     }
    333 
    334     /* calculate the average of the temporal rate */
    335     dRate->axx += x * x;
    336     dRate->ax  += x;
    337     dRate->an  ++;
    338 
    339     dRate->txx = dRate->tx = dRate->tn = 0;
    340 }
    341 
    342 static void delay_add(PERF_RTdata_delay *dDelay, unsigned long delta)
    343 {
    344     dDelay->x  += delta;
    345     dDelay->xx += delta * (double) delta;
    346     dDelay->n  ++;
    347 }
    348 
    349 static void delay_delta(PERF_RTdata_delay *dDelay, PERF_Private *perf)
    350 {
    351     if (dDelay->n < 0)
    352     {
    353         dDelay->n++;
    354     }
    355     else
    356     {
    357         delay_add(dDelay, TIME_DELTA(perf->time, dDelay->last_timestamp));
    358     }
    359     TIME_COPY(dDelay->last_timestamp, perf->time);
    360 }
    361 
    362 static void count_delay(PERF_RT_Private *me, char *tag, PERF_RTdata_delay *dDelay, long n0)
    363 {
    364     fprintf(me->fRt, "rtPERF: %s[0x%lX]: ", tag, me->dSTS->size_min);
    365     if (dDelay->n > 0)
    366     {
    367         double x = 1e-6 * dDelay->x / dDelay->n;
    368         double xx = 1e-12 * dDelay->xx / dDelay->n;
    369         xx = my_sqrt(xx - x * x);
    370 
    371         if (dDelay->n > 1)
    372         {
    373             fprintf(me->fRt, "%.3g +- %.3g s (%ld samples)\n",
    374                     x, xx, dDelay->n);
    375         }
    376         else
    377         {
    378             fprintf(me->fRt, "%.3g\n", x);
    379         }
    380     }
    381     else
    382     {
    383         fprintf(me->fRt, "UNABLE TO CALCULATE\n");
    384     }
    385 
    386     dDelay->n = n0;
    387     dDelay->xx = dDelay->x = 0;
    388 }
    389 
    390 void __rt_Boundary(PERF_Private *perf, PERF_BOUNDARYTYPE eBoundary)
    391 {
    392     /* get real-time private structure */
    393     PERF_RT_Private *me = perf->cip.pRT;
    394 
    395     /* check steady state if we need it */
    396     if (me->needSteadyState)
    397     {
    398         if (eBoundary == (PERF_BoundaryStart | PERF_BoundarySteadyState))
    399         {
    400             if (!me->steadyState)
    401             {
    402                 /* continue uptime measurement */
    403                 start_stop_uptime(me->dUptime, 1);
    404 
    405                 /* for each rate, reset skip count as well as tn0 */
    406                 int i;
    407                 for (i = 0; i < me->nDRate; i++)
    408                 {
    409                     me->dRate[i].txx = me->dRate[i].tx = me->dRate[i].tn = me->dRate[i].tn0 = 0;
    410                     me->dRate[i].skip = 0;
    411                 }
    412             }
    413 
    414             me->steadyState = 1;
    415         }
    416         else if (eBoundary == (PERF_BoundaryComplete | PERF_BoundarySteadyState))
    417         {
    418             if (me->steadyState)
    419             {
    420                 /* stop uptime measurement */
    421                 start_stop_uptime(me->dUptime, 0);
    422 
    423                 /* complete any temporary rate measurements */
    424                 int i;
    425                 for (i = 0; i < me->nDRate; i++)
    426                 {
    427                     /* only if we had any buffers in this cycle */
    428                     if (me->dRate[i].tn0 >= MIN_FRAMES_FOR_RATE ||
    429                         (me->dRate[i].tn && me->debug & 4))
    430                     {
    431                         count_temporal_rate(perf->ulID, me, me->dRate + i);
    432                     }
    433                 }
    434             }
    435 
    436             me->steadyState = 0;
    437         }
    438     }
    439     else
    440     {
    441         /* if we do not check steady state, we still complete on cleanup */
    442         if (eBoundary == (PERF_BoundaryStart | PERF_BoundaryCleanup))
    443         {
    444             /* stop measurements */
    445             start_stop_uptime(me->dUptime, 0);
    446         }
    447     }
    448 }
    449 
    450 void __rt_Buffer(PERF_Private *perf,
    451                  unsigned long ulAddress1,
    452                  unsigned long ulAddress2,
    453                  unsigned long ulSize,
    454                  PERF_MODULETYPE eModuleAndFlags)
    455 {
    456     /* get real-time private structure */
    457     PERF_RT_Private *me = perf->cip.pRT;
    458 
    459     /* see if we care about this buffer in the rate calculation */
    460     unsigned long module = eModuleAndFlags & PERF_ModuleMask;
    461 
    462     /* ------------------------ RATE METRICS ------------------------ */
    463 
    464     /* change HLMM to LLMM for detailed = 0 and 1 */
    465     if (me->detailed < 2 && module == PERF_ModuleHLMM)
    466     {
    467         module = PERF_ModuleLLMM;
    468     }
    469 
    470     int rate = (me->detailed == 2) ||
    471                (me->detailed == 0 &&
    472                 (eModuleAndFlags == me->only_moduleandflags && ulSize >= 8)) ||
    473                (me->detailed == 1 &&
    474                 ((module == PERF_ModuleHardware || module == PERF_ModuleLLMM)));
    475 
    476     if (rate && me->dRate && (!me->needSteadyState || me->steadyState))
    477     {
    478         /* change encoded filled frame sizes to 0xBEEFED, as they tend to
    479            have varying sizes and thus not be counted */
    480         unsigned long sending = PERF_GetXferSendRecv(eModuleAndFlags);
    481         unsigned long size = ulSize;
    482         if ((me->encoder || me->decoder) && !PERF_IsXfering(sending))
    483         {
    484             /* reverse sending direction to common layer or socket node */
    485             if (module >= PERF_ModuleCommonLayer &&
    486                 module <= PERF_ModuleSocketNode)
    487             {
    488                 sending ^= PERF_FlagSending;
    489             }
    490 
    491             if ((me->encoder && (sending == PERF_FlagSending)) ||
    492                 (me->decoder && (sending == PERF_FlagReceived)))
    493             {
    494                 size = size ? 0xBEEFED : 0;
    495             }
    496         }
    497 
    498         /* see if we are tracking this buffer size */
    499         int i, j = -1;  /* j is one of the lest used indexes */
    500         for (i=0; i < me->nDRate; i++)
    501         {
    502             if (me->dRate[i].modulesAndFlags == eModuleAndFlags &&
    503                 me->dRate[i].size == size) break;
    504             if (j < 0 || me->dRate[i].n < me->dRate[j].n)
    505             {
    506                 j = i;
    507             }
    508         }
    509 
    510         /* if we are not yet tracking this buffer, see if we can track
    511            it. */
    512         if (i == me->nDRate)
    513         {
    514             /* we have space to track it */
    515             if (i < me->maxDRate)
    516             {
    517                 me->nDRate++;
    518             }
    519             /* if we cannot replace another rate, we don't track it */
    520             else if (j < 0 || me->dRate[j].n < 2)
    521             {
    522                 i = me->maxDRate;
    523             }
    524             else
    525             {
    526                 i = j;
    527             }
    528 
    529             /* start tracking */
    530             if (i < me->maxDRate)
    531             {
    532                 me->dRate[i].modulesAndFlags = eModuleAndFlags;
    533                 me->dRate[i].size = size;
    534                 me->dRate[i].xx = me->dRate[i].x = me->dRate[i].n = 0;
    535                 me->dRate[i].txx = me->dRate[i].tx = me->dRate[i].tn = me->dRate[i].tn0 = 0;
    536                 me->dRate[i].axx = me->dRate[i].ax = me->dRate[i].an = 0;
    537                 me->dRate[i].skip = me->needSteadyState ? 0 : 4;
    538                 TIME_COPY(me->dRate[i].last_timestamp, perf->time);
    539                 TIME_COPY(me->dRate[i].last_reporting, perf->time);
    540             }
    541         }
    542         else
    543         {
    544             if (me->dRate[i].skip == 0)
    545             {
    546                 /* see if we passed our granularity */
    547                 int steps = TIME_DELTA(perf->time, me->dRate[i].last_reporting);
    548                 if (steps >= me->granularity)
    549                 {
    550                     steps /= me->granularity;
    551 
    552                     /* unless debug bit 4 is set, ignore temporal statistics if
    553                        we passed the last time by more than a second, and less than
    554                        the minimul frames were processed in this burst so far, and
    555                        the last fps was less than 1. */
    556                     if (!(me->debug & 4) &&
    557                         (me->dRate[i].tn0 < MIN_FRAMES_FOR_RATE) &&
    558                         (me->dRate[i].tn < me->granularity * steps))
    559                     {
    560                         if (me->debug & 256)
    561                         {
    562                             fprintf(me->fRt, "rtPERF: [%ld] IGNORED (steps=%d, tn0=%ld, tn=%ld)\n",
    563                                     TIME_DELTA(me->dRate[i].last_reporting, me->first_time)/1000000,
    564                                     steps, me->dRate[i].tn0, me->dRate[i].tn);
    565                         }
    566                         me->dRate[i].txx = me->dRate[i].tx = me->dRate[i].tn = me->dRate[i].tn0 = 0;
    567 
    568                         TIME_INCREASE(me->dRate[i].last_reporting, me->granularity * steps);
    569                         steps = 0;
    570                     }
    571                     else if (me->debug & 256)
    572                     {
    573                         fprintf(me->fRt, "rtPERF: [%ld] not-ignored (steps=%d, tn0=%ld, tn=%ld)\n",
    574                                 TIME_DELTA(me->dRate[i].last_reporting, me->first_time)/1000000,
    575                                 steps, me->dRate[i].tn0, me->dRate[i].tn);
    576                     }
    577 
    578                     /* see if we surpassed our granularity.  if yes, calculate
    579                        temporal statistics */
    580                     while (steps)
    581                     {
    582                         /* count temporal rate */
    583                         count_temporal_rate(perf->ulID, me, me->dRate + i);
    584 
    585                         TIME_INCREASE(me->dRate[i].last_reporting, me->granularity);
    586                         steps--;
    587                     }
    588                 }
    589 
    590                 /* rate is */
    591                 unsigned long delta = TIME_DELTA(perf->time, me->dRate[i].last_timestamp);
    592                 me->dRate[i].x   += delta;
    593                 me->dRate[i].tx  += delta;
    594                 me->dRate[i].xx  += delta * (double) delta;
    595                 me->dRate[i].txx += delta * (double) delta;
    596                 me->dRate[i].n   ++;
    597                 me->dRate[i].tn  ++;
    598                 me->dRate[i].tn0 ++;
    599             }
    600             else
    601             {
    602                 me->dRate[i].skip--;
    603                 if (me->dRate[i].skip == 0)
    604                 {
    605                     TIME_COPY(me->dRate[i].last_reporting, perf->time);
    606                     me->dRate[i].txx = me->dRate[i].tx = me->dRate[i].tn = 0;
    607                 }
    608             }
    609 
    610             TIME_COPY(me->dRate[i].last_timestamp, perf->time);
    611         }
    612     }
    613 
    614     /* ------------------------ SHOT-TO-SHOT METRICS ------------------------ */
    615     if (me->dSTS)
    616     {
    617         if (eModuleAndFlags == (PERF_FlagSending | PERF_FlagFrame | PERF_ModuleHardware))
    618         {
    619             /* queueing buffers to camera */
    620 
    621             /* see if resolution has changed */
    622             if (ulSize < me->dSTS->size_min ||
    623                 ulSize > me->dSTS->size_max)
    624             {
    625                 /* report burst rate if we have any */
    626                 if (me->debug)
    627                 {
    628                     if (me->dSTS->dBurst2.n > 0)
    629                     {
    630                         count_delay(me, "Modified burst shot-to-shot", &me->dSTS->dBurst2, 0);
    631                     }
    632                     if (me->dSTS->dBurst.n > 0)
    633                     {
    634                         count_delay(me, "Raw burst shot-to-shot", &me->dSTS->dBurst, -1);
    635                     }
    636                 }
    637 
    638                 me->dSTS->dBurst.n = -1;
    639                 me->dSTS->dBurst2.n = 0;
    640 
    641                 /* set new size */
    642                 me->dSTS->size_min = ulSize > 2048 ? ulSize - 2048 : 0;
    643                 me->dSTS->size_max = ulSize;
    644 
    645                 /* if more than D1-PAL, we assume it is an image, not a preview */
    646                 if (ulSize > 0x119000)
    647                 {
    648                     /* new burst mode start */
    649                     me->dSTS->capturing = 1;
    650                 }
    651                 else
    652                 {
    653                     /* preview start */
    654                     me->dSTS->capturing = 0;
    655                 }
    656             }
    657         }
    658         else if (eModuleAndFlags == (PERF_FlagReceived | PERF_FlagFrame | PERF_ModuleHardware))
    659         {
    660             /* gotten buffers from camera */
    661             if (me->dSTS->capturing &&
    662                 ulSize >= me->dSTS->size_min &&
    663                 ulSize <= me->dSTS->size_max)
    664             {
    665                 /* see if we have a capture already (we ignore the first) to
    666                    count into the modified capture */
    667                 if (me->dSTS->dBurst.n > 1)
    668                 {
    669                     /* count last time delta */
    670                     if (me->dSTS->dBurst.n > 2)
    671                     {
    672                         delay_add(&me->dSTS->dBurst2, me->dSTS->last_burst);
    673                         delay_add(&me->dSTS->dABurst2, me->dSTS->last_burst);
    674                         if (me->debug)
    675                         {
    676                             fprintf(me->fRt, "rtPERF: [%ld] Modified burst shot-to-shot[0x%lX]: %.3g s\n",
    677                                     me->dSTS->dBurst2.n, me->dSTS->size_min, 1e-6 * me->dSTS->last_burst);
    678                         }
    679                     }
    680                     me->dSTS->last_burst = TIME_DELTA(perf->time, me->dSTS->dBurst.last_timestamp);
    681                 }
    682                 else if (me->dSTS->dBurst.n < 0)
    683                 {
    684                     /* if this is the first shot in the burst sequence */
    685                     /* calculate single shot-to-shot delay */
    686                     if (me->dSTS->dSingle.n >= 0)
    687                     {
    688                         if (me->debug)
    689                         {
    690                             fprintf(me->fRt, "rtPERF: [#%ld] Single shot-to-shot[0x%lX]: %.3g s\n",
    691                                     me->dSTS->dSingle.n + 1, me->dSTS->size_min, 1e-6 * TIME_DELTA(perf->time, me->dSTS->dSingle.last_timestamp));
    692                         }
    693                         delay_delta(&me->dSTS->dSingle, perf);
    694                     }
    695                 }
    696 
    697                 if (me->dSTS->dBurst.n >= 0)
    698                 {
    699                     if (me->debug)
    700                     {
    701                         fprintf(me->fRt, "rtPERF: [#%ld] Raw burst shot-to-shot[0x%lX]: %.3g s\n",
    702                                 me->dSTS->dBurst.n + 1, me->dSTS->size_min, 1e-6 * TIME_DELTA(perf->time, me->dSTS->dBurst.last_timestamp));
    703                     }
    704                     delay_add(&me->dSTS->dABurst, TIME_DELTA(perf->time, me->dSTS->dBurst.last_timestamp));
    705                 }
    706                 delay_delta(&me->dSTS->dBurst, perf);
    707 
    708                 /* keep last captured image time stamp for single shot-to-shot */
    709                 TIME_COPY(me->dSTS->dSingle.last_timestamp, perf->time);
    710                 if (me->dSTS->dSingle.n < 0)
    711                 {
    712                     me->dSTS->dSingle.n = 0;  /* captured first time stamp */
    713                 }
    714             }
    715         }
    716     }
    717 
    718     /* ------------------------ UPTIME METRICS ------------------------ */
    719     if (0 && me->dUptime && me->dUptime->measuring)
    720     {
    721         /* see if we passed our granularity.  if yes, calculate uptime */
    722         int steps = TIME_DELTA(perf->time, me->dUptime->last_reporting);
    723         if (steps >= me->granularity)
    724         {
    725             steps /= me->granularity;
    726 
    727             double uptime, idletime, load = 0;
    728 
    729             /* calculate MHz load */
    730             get_uptime(&uptime, &idletime);
    731             if (uptime > 0 && me->dUptime->success)
    732             {
    733                 me->dUptime->last_idletime = idletime - me->dUptime->last_idletime;
    734                 me->dUptime->last_uptime = uptime - me->dUptime->last_uptime;
    735                 if (me->dUptime->last_uptime > 0)
    736                 {
    737                     load = 100. * ((me->dUptime->last_uptime - me->dUptime->last_idletime) /
    738                                    me->dUptime->last_uptime);
    739 
    740                     me->dUptime->n += steps;
    741                     me->dUptime->x += load * steps;
    742                     me->dUptime->xx += load * load * steps;
    743                 }
    744             }
    745 
    746             TIME_INCREASE(me->dUptime->last_reporting, steps * me->granularity);
    747 
    748             if (uptime > 0 && me->dUptime->success)
    749             {
    750                 me->dUptime->last_uptime = uptime;
    751                 me->dUptime->last_idletime = idletime;
    752                 if (me->debug)
    753                 {
    754                     fprintf(me->fRt, "rtPERF: [%ld] ARM CPU-load is %.3g%%\n",
    755                             TIME_DELTA(perf->time, me->first_time)/1000000,
    756                             load);
    757                 }
    758             }
    759             else
    760             {
    761                 me->dUptime->success = 0;
    762             }
    763         }
    764     }
    765 }
    766 
    767 void __rt_Command(PERF_Private *perf,
    768                   unsigned long ulCommand,
    769                   unsigned long ulArgument,
    770                   PERF_MODULETYPE eModule)
    771 {
    772     /* get real-time private structure */
    773     /* PERF_RT_Private *me = perf->cip.pRT; */
    774 
    775     /* there is nothing to do at this point */
    776 }
    777 
    778 void __rt_Log(PERF_Private *perf,
    779               unsigned long ulData1, unsigned long ulData2,
    780               unsigned long ulData3)
    781 {
    782     /* get real-time private structure */
    783     /* PERF_RT_Private *me = perf->cip.pRT; */
    784 
    785     /* there is nothing to do at this point */
    786 }
    787 
    788 void __rt_SyncAV(PERF_Private *perf,
    789                  float pfTimeAudio,
    790                  float pfTimeVideo,
    791                  PERF_SYNCOPTYPE eSyncOperation)
    792 {
    793     /* get real-time private structure */
    794     /* PERF_RT_Private *me = perf->cip.pRT; */
    795 
    796     /* there is nothing to do at this point */
    797 }
    798 
    799 void __rt_ThreadCreated(PERF_Private *perf,
    800                         unsigned long ulThreadID,
    801                         unsigned long ulThreadName)
    802 {
    803     /* get real-time private structure */
    804     /* PERF_RT_Private *me = perf->cip.pRT; */
    805 
    806     /* there is nothing to do at this point. Perhaps we can enable uptime if
    807        we still have not created it and it is an audio thread. */
    808 }
    809 
    810 void __rt_Done(PERF_Private *perf)
    811 {
    812     /* get real-time private structure */
    813     PERF_RT_Private *me = perf->cip.pRT;
    814 
    815     /* print summaries if required */
    816     if (me->summary)
    817     {
    818         /* uptime summary */
    819         if (me->dUptime)
    820         {
    821             /* get last uptime */
    822             start_stop_uptime(me->dUptime, 0);
    823 
    824             fprintf(me->fRt, "rtPERF: ARM CPU-load for%s %c%c%c%c component: ",
    825                     me->needSteadyState ? " steady state of" : "",
    826                     PERF_FOUR_CHARS(perf->ulID));
    827 
    828             if (me->dUptime->success && me->dUptime->start_uptime)
    829             {
    830                 double load = (100. * (me->dUptime->start_uptime -
    831                                       me->dUptime->start_idletime) /
    832                                me->dUptime->start_uptime);
    833                 if (me->dUptime->n)
    834                 {
    835                     double x = me->dUptime->x / me->dUptime->n;
    836                     double xx = me->dUptime->xx / me->dUptime->n;
    837                     xx = my_sqrt(xx - x * x);
    838                     if (me->debug & 2)
    839                     {
    840                         fprintf(me->fRt, ": %.3g +- %.3g%%\n"
    841                                 "(temporal difference is: %.3g)\n",
    842                                 load, xx, x - load);
    843                     }
    844                     else
    845                     {
    846                         fprintf(me->fRt, ": %.3g +- %.3g%%\n",
    847                                 load, xx);
    848                     }
    849                 }
    850                 else
    851                 {
    852                     fprintf(me->fRt, "%.3g%%\n", load);
    853                 }
    854             }
    855             else
    856             {
    857                 fprintf(me->fRt, "FAILED TO CALCULATE\n");
    858             }
    859         }
    860 
    861         /* rate summary */
    862         if (me->nDRate)
    863         {
    864             int i;
    865             for (i = 0; i < me->nDRate; i++)
    866             {
    867                 if (me->dRate[i].n >= MIN_FRAMES_FOR_RATE &&
    868                     ((me->debug & 4) || me->dRate[i].tn0 >= MIN_FRAMES_FOR_RATE))
    869                 {
    870 
    871                     double x = me->dRate[i].x * 1e-6 / me->dRate[i].n;
    872 
    873                     double s = (me->dRate[i].xx ?
    874                                 (me->dRate[i].x * (double) me->dRate[i].x /
    875                                  me->dRate[i].xx / me->dRate[i].n) : 1);
    876 
    877                     fprintf(me->fRt, "rtPERF: ");
    878                     print_rate_info(me->fRt,
    879                                     perf->ulID, me->dRate[i].modulesAndFlags,
    880                                     me->dRate[i].size, me->dRate[i].n);
    881                     if (x > 0)
    882                     {
    883                         if (me->dRate[i].an)
    884                         {
    885                             double x2 = me->dRate[i].ax / me->dRate[i].an;
    886                             double xx = me->dRate[i].axx / me->dRate[i].an;
    887                             xx = my_sqrt(xx - x2 * x2);
    888                             if (me->debug & 2)
    889                             {
    890                                 fprintf(me->fRt, ": %.3g +- %.3g fps (s=%.3g)\n"
    891                                         "(temporal difference is: %.3g)\n",
    892                                         1/x, xx, s, x2-1/x);
    893                             }
    894                             else
    895                             {
    896                                 fprintf(me->fRt, ": %.3g +- %.3g fps (s=%.3g)\n",
    897                                         1/x, xx, s);
    898                             }
    899                         }
    900                         else
    901                         {
    902                             fprintf(me->fRt, ": %.3g fps (s=%.3g)\n", 1/x, s);
    903                         }
    904                     }
    905                     else
    906                     {
    907                         fprintf(me->fRt, ": FAILED TO CALCULATE\n");
    908                     }
    909                 }
    910             }
    911         }
    912 
    913         /* shot-to-shot summary */
    914         if (me->dSTS)
    915         {
    916             if (me->dSTS->dABurst2.n > 0)
    917             {
    918                 count_delay(me, "Avg. modified burst shot-to-shot", &me->dSTS->dABurst2, 0);
    919             }
    920             if (me->dSTS->dABurst.n > 0)
    921             {
    922                 count_delay(me, "Avg. raw burst shot-to-shot", &me->dSTS->dABurst, 0);
    923             }
    924             if (me->dSTS->dSingle.n > 0)
    925             {
    926                 count_delay(me, "Avg. single shot-to-shot", &me->dSTS->dSingle, -1);
    927             }
    928         }
    929     }
    930 }
    931 
    932 
    933 #endif
    934