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