#pragma once #include "CadenceTelemetry.h" #include #include #include #include #include namespace RenderCadenceCompositor { struct TelemetryPrinterConfig { std::chrono::milliseconds interval = std::chrono::seconds(1); }; class TelemetryPrinter { public: explicit TelemetryPrinter(TelemetryPrinterConfig config = TelemetryPrinterConfig()) : mConfig(config) { } TelemetryPrinter(const TelemetryPrinter&) = delete; TelemetryPrinter& operator=(const TelemetryPrinter&) = delete; ~TelemetryPrinter() { Stop(); } template void Start(const SystemFrameExchange& exchange, const DeckLinkOutput& output, const OutputThread& outputThread) { if (mRunning) return; mStopping = false; mThread = std::thread([this, &exchange, &output, &outputThread]() { CadenceTelemetry telemetry; while (!mStopping) { std::this_thread::sleep_for(mConfig.interval); Print(telemetry.Sample(exchange, output, outputThread)); } }); mRunning = true; } void Stop() { mStopping = true; if (mThread.joinable()) mThread.join(); mRunning = false; } private: static void Print(const CadenceTelemetrySnapshot& snapshot) { std::cout << std::fixed << std::setprecision(1) << "renderFps=" << snapshot.renderFps << " scheduleFps=" << snapshot.scheduleFps << " free=" << snapshot.freeFrames << " completed=" << snapshot.completedFrames << " scheduled=" << snapshot.scheduledFrames << " completedPollMisses=" << snapshot.completedPollMisses << " scheduleFailures=" << snapshot.scheduleFailures << " completions=" << snapshot.completions << " late=" << snapshot.displayedLate << " dropped=" << snapshot.dropped << " decklinkBuffered="; if (snapshot.deckLinkBufferedAvailable) std::cout << snapshot.deckLinkBuffered; else std::cout << "n/a"; std::cout << " scheduleCallMs=" << snapshot.deckLinkScheduleCallMilliseconds << "\n"; } TelemetryPrinterConfig mConfig; std::thread mThread; std::atomic mStopping{ false }; std::atomic mRunning{ false }; }; }