1 /**************************************************************************
2 *
3 * Copyright (C) 2017 tint2 authors
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License version 2
7 * as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16 **************************************************************************/
17 
18 #include <stdlib.h>
19 
20 #include "fps_distribution.h"
21 
22 static float *fps_distribution = NULL;
23 
init_fps_distribution()24 void init_fps_distribution()
25 {
26     // measure FPS with resolution:
27     // 0-59: 1		   (60 samples)
28     // 60-199: 10      (14)
29     // 200-1,999: 25   (72)
30     // 1k-19,999: 1000 (19)
31     // 20x+: inf       (1)
32     // => 166 samples
33     if (fps_distribution)
34         return;
35     fps_distribution = calloc(170, sizeof(float));
36 }
37 
cleanup_fps_distribution()38 void cleanup_fps_distribution()
39 {
40     free(fps_distribution);
41     fps_distribution = NULL;
42 }
43 
sample_fps(double fps)44 void sample_fps(double fps)
45 {
46     int fps_rounded = (int)(fps + 0.5);
47     int i = 1;
48     if (fps_rounded < 60) {
49         i += fps_rounded;
50     } else {
51         i += 60;
52         if (fps_rounded < 200) {
53             i += (fps_rounded - 60) / 10;
54         } else {
55             i += 14;
56             if (fps_rounded < 2000) {
57                 i += (fps_rounded - 200) / 25;
58             } else {
59                 i += 72;
60                 if (fps_rounded < 20000) {
61                     i += (fps_rounded - 2000) / 1000;
62                 } else {
63                     i += 20;
64                 }
65             }
66         }
67     }
68     // fprintf(stderr, "tint2: fps = %.0f => i = %d\n", fps, i);
69     fps_distribution[i] += 1.;
70     fps_distribution[0] += 1.;
71 }
72 
fps_compute_stats(double * low,double * median,double * high,double * samples)73 void fps_compute_stats(double *low, double *median, double *high, double *samples)
74 {
75     *median = *low = *high = *samples = -1;
76     if (!fps_distribution || fps_distribution[0] < 1)
77         return;
78     float total = fps_distribution[0];
79     *samples = (double)fps_distribution[0];
80     float cum_low = 0.05f * total;
81     float cum_median = 0.5f * total;
82     float cum_high = 0.95f * total;
83     float cum = 0;
84     for (int i = 1; i <= 166; i++) {
85         double value =
86             (i < 60) ? i : (i < 74) ? (60 + (i - 60) * 10) : (i < 146) ? (200 + (i - 74) * 25)
87                                                                        : (i < 165) ? (2000 + (i - 146) * 1000) : 20000;
88         // fprintf(stderr, "tint2: %6.0f (i = %3d) : %.0f | ", value, i, (double)fps_distribution[i]);
89         cum += fps_distribution[i];
90         if (*low < 0 && cum >= cum_low)
91             *low = value;
92         if (*median < 0 && cum >= cum_median)
93             *median = value;
94         if (*high < 0 && cum >= cum_high)
95             *high = value;
96     }
97 }
98