/** * fc_test_consumer.c — Dev utility: attach to a framecache slot and print stats. * * Usage: fc_test_consumer [wait_ms] */ #include "fc_client.h" #include #include #include #include static volatile int g_run = 1; static void on_sig(int s) { (void)s; g_run = 0; } int main(int argc, char **argv) { if (argc < 2) { fprintf(stderr, "Usage: %s [wait_ms]\n", argv[0]); return 1; } const char *slot_id = argv[1]; uint64_t wait_ms = argc >= 3 ? (uint64_t)atoi(argv[2]) : 30000; signal(SIGINT, on_sig); signal(SIGTERM, on_sig); fprintf(stderr, "Opening slot '%s' (wait up to %llums)...\n", slot_id, (unsigned long long)wait_ms); fc_consumer_t *c = fc_consumer_open(slot_id, wait_ms); if (!c) { fprintf(stderr, "Failed to open slot '%s'\n", slot_id); return 1; } fprintf(stderr, "Slot opened. Reading frames (Ctrl+C to stop)...\n"); uint64_t total = 0, dropped = 0; struct timespec t0; clock_gettime(CLOCK_MONOTONIC, &t0); while (g_run) { fc_frame_ref_t ref; int rc = fc_consumer_read(c, &ref, 2000); if (rc == FC_TIMEOUT) continue; if (rc == FC_ERROR) { fprintf(stderr, "read error\n"); break; } if (rc == FC_LAPPED) { /* torn copy — no valid frame, read again */ continue; } if (rc == FC_DROPPED) { dropped = fc_consumer_dropped(c); fprintf(stderr, "[WARN] consumer fell behind — total dropped: %llu\n", (unsigned long long)dropped); } total++; /* Print stats every 100 frames */ if (total % 100 == 0) { struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); double elapsed = (now.tv_sec - t0.tv_sec) + (now.tv_nsec - t0.tv_nsec) * 1e-9; fprintf(stdout, "frames=%llu dropped=%llu fps=%.2f pts_us=%llu\n", (unsigned long long)total, (unsigned long long)fc_consumer_dropped(c), total / elapsed, (unsigned long long)ref.pts_us); fflush(stdout); } } fprintf(stderr, "Done. total=%llu dropped=%llu\n", (unsigned long long)total, (unsigned long long)fc_consumer_dropped(c)); fc_consumer_close(c); return 0; }