ascii-chat 0.8.38
Real-time terminal-based video chat with ASCII art conversion
Loading...
Searching...
No Matches
fps.c
Go to the documentation of this file.
1
7#include <ascii-chat/util/fps.h>
8#include <ascii-chat/common.h>
9#include <ascii-chat/util/time.h>
10#include <ascii-chat/log/logging.h>
11
15static void log_fps_report(const char *tracker_name, double actual_fps, uint64_t frame_count, double elapsed_seconds) {
16 log_dev_every(4500 * US_PER_MS_INT, "[%s] %.1f fps (%llu frames in %.1fs)", tracker_name, actual_fps,
17 (unsigned long long)frame_count, elapsed_seconds);
18}
19
25static void log_lag_event(const char *tracker_name, const char *context, double late_ms, double expected_ms,
26 double actual_ms, double actual_fps) {
27 // Rate limit to once per second to avoid log spam
28 log_warn_every(NS_PER_MS_INT, "[%s] LAG: %s late by %.1fms (expected %.1fms, got %.1fms, %.2f fps)", tracker_name,
29 context, late_ms, expected_ms, actual_ms, actual_fps);
30}
31
32void fps_init(fps_t *tracker, int expected_fps, const char *name) {
33 // Default report interval: 1 second
34 fps_init_with_interval(tracker, expected_fps, name, 1 * NS_PER_SEC_INT);
35}
36
37void fps_init_with_interval(fps_t *tracker, int expected_fps, const char *name, uint64_t report_interval_ns) {
38 if (!tracker) {
39 return;
40 }
41
42 tracker->frame_count = 0;
43 tracker->expected_fps = expected_fps > 0 ? expected_fps : 60;
44 tracker->tracker_name = name ? name : "FPS";
45 tracker->report_interval_ns = report_interval_ns;
46
47 // Initialize timestamps to zero (will be set on first frame)
48 tracker->last_fps_report_ns = 0;
49 tracker->last_frame_time_ns = 0;
50}
51
52void fps_frame_ns(fps_t *tracker, uint64_t current_time_ns, const char *context) {
53 if (!tracker) {
54 return;
55 }
56
57 // Initialize on first frame
58 if (tracker->last_fps_report_ns == 0) {
59 tracker->last_fps_report_ns = current_time_ns;
60 tracker->last_frame_time_ns = current_time_ns;
61 }
62
63 tracker->frame_count++;
64
65 // Calculate time since last frame in nanoseconds
66 uint64_t frame_interval_ns = time_elapsed_ns(tracker->last_frame_time_ns, current_time_ns);
67 tracker->last_frame_time_ns = current_time_ns;
68
69 // Expected frame interval in nanoseconds
70 // For 60 FPS: 1 second / 60 = 16,666,666 ns per frame
71 uint64_t expected_interval_ns = NS_PER_SEC_INT / (uint64_t)tracker->expected_fps;
72 uint64_t lag_threshold_ns = expected_interval_ns + (expected_interval_ns / 2); // 50% over expected
73
74 // Log error if frame arrived too late (only after first frame)
75 if (tracker->frame_count > 1 && frame_interval_ns > lag_threshold_ns) {
76 const char *context_str = context ? context : "Frame";
77
78 // Convert to milliseconds for display (but calculations stay in nanoseconds)
79 double late_ms = time_ns_to_us(frame_interval_ns - expected_interval_ns) / 1000.0;
80 double expected_ms = time_ns_to_us(expected_interval_ns) / 1000.0;
81 double actual_ms = time_ns_to_us(frame_interval_ns) / 1000.0;
82 double actual_fps = 1e9 / (double)frame_interval_ns;
83
84 log_lag_event(tracker->tracker_name, context_str, late_ms, expected_ms, actual_ms, actual_fps);
85 }
86
87 // Report FPS every report_interval_ns
88 uint64_t elapsed_ns = time_elapsed_ns(tracker->last_fps_report_ns, current_time_ns);
89
90 if (elapsed_ns >= tracker->report_interval_ns) {
91 double elapsed_seconds = time_ns_to_s(elapsed_ns);
92 double actual_fps = (double)tracker->frame_count / elapsed_seconds;
93 log_fps_report(tracker->tracker_name, actual_fps, tracker->frame_count, elapsed_seconds);
94
95 // Reset counters for next interval
96 tracker->frame_count = 0;
97 tracker->last_fps_report_ns = current_time_ns;
98 }
99}
void fps_init_with_interval(fps_t *tracker, int expected_fps, const char *name, uint64_t report_interval_ns)
Definition fps.c:37
void fps_frame_ns(fps_t *tracker, uint64_t current_time_ns, const char *context)
Definition fps.c:52
void fps_init(fps_t *tracker, int expected_fps, const char *name)
Definition fps.c:32
uint64_t time_elapsed_ns(uint64_t start_ns, uint64_t end_ns)
Definition util/time.c:90