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 
init_delay(PERF_RTdata_delay * dDelay,long n0)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 *
PERF_RT_create(PERF_Private * perf,PERF_Config * config,PERF_MODULETYPE eModule)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 
PERF_RT_done(PERF_Private * perf)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 
get_uptime(double * uptime,double * idletime)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 
start_stop_uptime(PERF_RTdata_uptime * dUptime,int start)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 
my_sqrt(double a)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 
print_rate_info(FILE * fOut,unsigned long ID,PERF_MODULETYPE modulesAndFlags,unsigned long size,long n)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 
count_temporal_rate(unsigned long ID,PERF_RT_Private * me,PERF_RTdata_rate * dRate)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 
delay_add(PERF_RTdata_delay * dDelay,unsigned long delta)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 
delay_delta(PERF_RTdata_delay * dDelay,PERF_Private * perf)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 
count_delay(PERF_RT_Private * me,char * tag,PERF_RTdata_delay * dDelay,long n0)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 
__rt_Boundary(PERF_Private * perf,PERF_BOUNDARYTYPE eBoundary)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 
__rt_Buffer(PERF_Private * perf,unsigned long ulAddress1,unsigned long ulAddress2,unsigned long ulSize,PERF_MODULETYPE eModuleAndFlags)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 
__rt_Command(PERF_Private * perf,unsigned long ulCommand,unsigned long ulArgument,PERF_MODULETYPE eModule)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 
__rt_Log(PERF_Private * perf,unsigned long ulData1,unsigned long ulData2,unsigned long ulData3)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 
__rt_SyncAV(PERF_Private * perf,float pfTimeAudio,float pfTimeVideo,PERF_SYNCOPTYPE eSyncOperation)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 
__rt_ThreadCreated(PERF_Private * perf,unsigned long ulThreadID,unsigned long ulThreadName)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 
__rt_Done(PERF_Private * perf)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