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