// Copyright 2024 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CAST_STREAMING_PUBLIC_STATISTICS_H_ #define CAST_STREAMING_PUBLIC_STATISTICS_H_ #include #include #include #include #include #include "cast/streaming/public/frame_id.h" #include "cast/streaming/rtp_time.h" #include "json/value.h" #include "platform/api/time.h" namespace openscreen::cast { // This file must be updated whenever sender_stats.proto is updated. enum class StatisticType { // Frame enqueuing rate. kEnqueueFps = 0, // Average capture latency in milliseconds. kAvgCaptureLatencyMs, // Average encode duration in milliseconds. kAvgEncodeTimeMs, // Duration from when a frame is encoded to when the packet is first // sent. kAvgQueueingLatencyMs, // Duration from when a packet is transmitted to when it is received. // This measures latency from sender to receiver. kAvgNetworkLatencyMs, // Duration from when a frame is encoded to when the packet is first // received. kAvgPacketLatencyMs, // Average latency between frame encoded and the moment when the frame // is fully received. kAvgFrameLatencyMs, // Duration from when a frame is captured to when it should be played out. kAvgEndToEndLatencyMs, // Encode bitrate in kbps. kEncodeRateKbps, // Packet transmission bitrate in kbps. kPacketTransmissionRateKbps, // Duration in milliseconds since the estimated last time the receiver sent // a response. kTimeSinceLastReceiverResponseMs, // Number of frames captured. kNumFramesCaptured, // Number of frames dropped by encoder. kNumFramesDroppedByEncoder, // Number of late frames. kNumLateFrames, // Number of packets that were sent. kNumPacketsSent, // Number of packets that were received by receiver. kNumPacketsReceived, // Unix time in milliseconds of first event since reset. kFirstEventTimeMs, // Unix time in milliseconds of last event since reset. kLastEventTimeMs, // The number of statistic types. kNumTypes = kLastEventTimeMs + 1 }; enum class HistogramType { // Histogram representing the capture latency (in milliseconds). kCaptureLatencyMs, // Histogram representing the encode time (in milliseconds). kEncodeTimeMs, // Histogram representing the queueing latency (in milliseconds). kQueueingLatencyMs, // Histogram representing the network latency (in milliseconds). kNetworkLatencyMs, // Histogram representing the packet latency (in milliseconds). kPacketLatencyMs, // Histogram representing the end to end latency (in milliseconds). kEndToEndLatencyMs, // Histogram representing how late frames are (in milliseconds). kFrameLatenessMs, // The number of histogram types. kNumTypes = kFrameLatenessMs + 1 }; struct SimpleHistogram { // This will create N+2 buckets where N = (max - min) / width: // Underflow bucket: < min // Bucket 0: [min, min + width - 1] // Bucket 1: [min + width, min + 2 * width - 1] // ... // Bucket N-1: [max - width, max - 1] // Overflow bucket: >= max // `min` must be less than `max`. // `width` must divide `max - min` evenly. SimpleHistogram(int64_t min, int64_t max, int64_t width); SimpleHistogram(); SimpleHistogram(const SimpleHistogram&); SimpleHistogram(SimpleHistogram&&) noexcept; SimpleHistogram& operator=(const SimpleHistogram&); SimpleHistogram& operator=(SimpleHistogram&&); ~SimpleHistogram(); bool operator==(const SimpleHistogram&) const; void Add(int64_t sample); void Reset(); Json::Value ToJson() const; std::string ToString() const; int64_t min = 1; int64_t max = 1; int64_t width = 1; std::vector buckets; private: SimpleHistogram(int64_t min, int64_t max, int64_t width, std::vector buckets); std::string GetBucketName(size_t index) const; }; std::ostream& operator<<(std::ostream& out, const SimpleHistogram& histogram); struct SenderStats { using StatisticsList = std::array(StatisticType::kNumTypes)>; using HistogramsList = std::array(HistogramType::kNumTypes)>; // The current audio statistics. StatisticsList audio_statistics = {}; // The current audio histograms. HistogramsList audio_histograms = {}; // The current video statistics. StatisticsList video_statistics = {}; // The current video histograms. HistogramsList video_histograms = {}; Json::Value ToJson() const; std::string ToString() const; }; std::ostream& operator<<(std::ostream& out, const SenderStats& stats); // The consumer may provide a statistics client if they are interested in // getting statistics about the ongoing session. class SenderStatsClient { public: // Gets called regularly with updated statistics while they are being // generated. virtual void OnStatisticsUpdated(const SenderStats& updated_stats) = 0; protected: virtual ~SenderStatsClient(); }; } // namespace openscreen::cast #endif // CAST_STREAMING_PUBLIC_STATISTICS_H_